各种排序算法的场景以及c++实现(插入排序,希尔排序,冒泡排序,快速排序,选择排序,归并排序)

对现有工作并不是很满意,所以决定找下一个坑。由工作中遇到排序场景并不多,大都是用冒泡排序,太low,面试又经常问到一些排序算法方面的东西。刚好让小学妹邮的数据结构也到了。就把各种排序算法重新总结一下,以作留存。


排序分为内部排序和外部排序,内部排序是在内存中排序。外部排序是由于排序记录量太大,内存一次放不下全部记录,排序过程中需要对外部存储访问的排序过程。外部排序用到的场景比较少,所以本次总结的都是内部排序。


排序安全:相同的元素相对位置不变,是排序安全,反之是不安全。


一,直接插入排序

基本思路:把一个元素插入到已排好的有序表中。(初始时认为是只有一个有序元素为有序表和其他无序元素)

应用场景:基本有序时复杂度为n。

是否排序安全:安全。

复杂度:O(n2).

代码:

//直接插入排序
void CSort::InsertSort(int *a, int len)
{
for (int i = 1; i < len; i++)
{
int key = a[i];
int j = i - 1;

//当前元素做为key
while (j>=0 && a[j] > key)
{

//不是元素应当插入时的位置,全部后移
a[j + 1] = a[j];
j--;
}

//插入元素到正确位置
a[j+1] = key;
}
}


二,希尔排序 

希尔排序是直接插入排序的改进。

基本思路:先将整个待排序记录按照增量分割成若干子序分别进行插入排序,基本有序时在进行一次直接插入排序。

实现:先使增量为长度的一半,在让增量变为增量的一半,使序列逐渐有序,增量为1时,等于对基本有序数列进行一次直接插入排序。

应用场景:基本有序时复杂度为n。

是否排序安全:不安全。

复杂度:O(n2).

代码:

//希尔插入,当增量为1时就是直接插入排序
void CSort::ShellInsert(int *a, int len, int dk)
{
for (int i = dk + 1; i < len; i++)
{
int key = a[i];
int j = i - dk;
while (j >= 0 && a[j] > key)
{
a[j +dk] = a[j];
j -= dk;
}
a[j + dk] = key;
}
}

//希尔排序
void CSort::ShellSort(int *a, int len)
{
int k = len / 2;
while (k >= 1)
{
ShellInsert(a, len, k);
k = k / 2;
}
}

三,冒泡排序

基本思路:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

是否排序安全:安全

代码:

void CSort::BubbleSort(int *a, int len)
{
for (int i = 0; i < len; i++)
{
for (int j = i + 1; j < len; j++)
{
if (a[i] > a[j])
{
swap(&a[i], &a[j]);
}
}
}
}

四,快速排序。(冒泡排序的优化)

基本思路:选取一个元素, 把表里的元素依次对比选取的元素,分割成2个表(此时元素以在最终的位置)。在依次对这两个表进行重复操作。次元素所在的位置就是最终其应该在的位置。当表里的元素数量为1时结束。

适用场景:快速排序是平均复杂度最低的排序。

是否排序安全:不安全

代码:

//快速排序
int CSort::Partition(int *a, int low, int high)
{
int key = a[low];
while (low < high)
{
while (low < high&&a[high] >= key) high--;
swap(&a[low],&a[high]);
while (low < high&&a[low] <= key) low++;
swap(&a[low],&a[high]);
}
return low;
}


void CSort::QuickSort(int *a, int low, int high)
{
if (low{
int index = Partition(a, low, high);
QuickSort(a, low, index - 1);
QuickSort(a, index + 1, high);
}
}


五,选择排序(简单选择排序)。

基本思路:每一趟循环都选择最小(大)的元素作为有序数列的第i个元素。

适用场景:

是否排序安全:不安全

代码:

void CSort::SelectSort(int *a, int len)
{
for (int i = 0; i < len; i++)
{
int index = i;
for (int j = i + 1; j < len; j++)
{
if (a[j] < a[index])
{
index = j;
}
}
swap(&a[index],&a[i]);
}
}


六,归并排序。

基本思路:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

归并排序示例:


复杂度:O(n)

使用场景:适用于很多元素而且无序的排序。

代码:

void CSort::Merge(int *r, int *rf, int i, int m, int n)
{
int j, k;
for (j = m + 1, k = i; i <= m && j <= n; ++k){
if (r[j] < r[i]) rf[k] = r[j++];
else rf[k] = r[i++];
}
while (i <= m)  rf[k++] = r[i++];
while (j <= n)  rf[k++] = r[j++];
}


void CSort::MergeSort(int *r, int *rf, int lenght)
{
int len = 1;
int *q = r;
int *tmp;
while (len < lenght) {
int s = len;
len = 2 * s;
int i = 0;
while (i + len < lenght){
Merge(q, rf, i, i + s - 1, i + len - 1); //对等长的两个子表合并  
i = i + len;
}
if (i + s < lenght){
Merge(q, rf, i, i + s - 1, lenght - 1); //对不等长的两个子表合并  
}
tmp = q; q = rf; rf = tmp; //交换q,rf,以保证下一趟归并时,仍从q 归并到rf  
}
}


下面附带实现的全部源码。

////////////////////////////////////////////////////////////
//
//                 SortTest.h
//
////////////////////////////////////////////////////////////
#ifndef __CSORT_TEST_H__
#define __CSORT_TEST_H__

#include 
#include 

class CSort
{
public:
	void swap(int *a,int *b);

	//直接插入排序
	void InsertSort(int *a, int len);

	//希尔排序
	void ShellInsert(int *a, int len, int dk/*增量*/);
	void ShellSort(int *a,int len);

	//快速排序
	void QuickSort(int *a,int low,int high);

	int Partition(int *a,int low,int high);

	//选择排序
	void SelectSort(int *a,int len);

	//冒泡排序
	void BubbleSort(int *a,int len);
	
	//归并排序
	void Merge(int *r, int *rf, int i, int m, int n);
	void MergeSort(int *r, int *rf, int lenght);
};

#endif

////////////////////////////////////////////////////////////
//
//                 SortTest.cpp
//
////////////////////////////////////////////////////////////

#include "SortTest.h"

void CSort::swap(int *a, int *b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
//直接插入排序
void CSort::InsertSort(int *a, int len)
{
	for (int i = 1; i < len; i++)
	{
		int key = a[i];
		int j = i - 1;
		while (j>=0 && a[j] > key)
		{
			a[j + 1] = a[j];
			j--;
		}

		a[j+1] = key;
	}
}

//希尔插入,当增量为1时就是直接插入排序
void CSort::ShellInsert(int *a, int len, int dk)
{
	for (int i = dk + 1; i < len; i++)
	{
		int key = a[i];
		int j = i - dk;
		while (j >= 0 && a[j] > key)
		{
			a[j +dk] = a[j];
			j -= dk;
		}
		a[j + dk] = key;
	}
}

//希尔排序
void CSort::ShellSort(int *a, int len)
{
	int k = len / 2;
	while (k >= 1)
	{
		ShellInsert(a, len, k);
		k = k / 2;
	}
}

//快速排序
int CSort::Partition(int *a, int low, int high)
{
	int key = a[low];
	while (low < high)
	{
		while (low < high&&a[high] >= key) high--;
		swap(&a[low],&a[high]);
		while (low < high&&a[low] <= key) low++;
		swap(&a[low],&a[high]);
	}
	return low;
}

void CSort::QuickSort(int *a, int low, int high)
{
	if (low a[j])
			{
				swap(&a[i], &a[j]);
			}
		}
	}
}

void CSort::Merge(int *r, int *rf, int i, int m, int n)
{
	int j, k;
	for (j = m + 1, k = i; i <= m && j <= n; ++k){
		if (r[j] < r[i]) rf[k] = r[j++];
		else rf[k] = r[i++];
	}
	while (i <= m)  rf[k++] = r[i++];
	while (j <= n)  rf[k++] = r[j++];
}

void CSort::MergeSort(int *r, int *rf, int lenght)
{
	int len = 1;
	int *q = r;
	int *tmp;
	while (len < lenght) {
		int s = len;
		len = 2 * s;
		int i = 0;
		while (i + len < lenght){
			Merge(q, rf, i, i + s - 1, i + len - 1); //对等长的两个子表合并  
			i = i + len;
		}
		if (i + s < lenght){
			Merge(q, rf, i, i + s - 1, lenght - 1); //对不等长的两个子表合并  
		}
		tmp = q; q = rf; rf = tmp; //交换q,rf,以保证下一趟归并时,仍从q 归并到rf  
	}
}

int main()
{
	CSort sort;
	int a[10] = {10,20,32,13,9,25,23,45,56,1};
	printf("\n排序前!");
	for (size_t i = 0; i < 10; i++)
	{
		printf("%d ", a[i]);
	}

	//sort.InsertSort(a, 10);
	//sort.ShellInsert(a, 10, 1);
	//sort.ShellSort(a, 10);
	//sort.QuickSort(a, 0, 9);
	//sort.SelectSort(a, 10);
	//sort.BubbleSort(a, 10);

	int b[10] = { 0 };
	sort.MergeSort(a,b,10);
	printf("\n排序后!");
	for (size_t i = 0; i < 10; i++)
	{
		printf("%d ", a[i]);
	}
	printf("hello world!\n");
	system("pause");
	return 0;
}



你可能感兴趣的:(c/c++)