常用排序算法总结(简单数组实现,其他类似)----- C语言


排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。分内部排序和外部排序。若整个排序过程不需
要访问外存便能完成,则称此类排序问题为内部排序。反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问
题为外部排序。内部排序的过程是一个逐步扩大记录的有序序列长度的过程。

我们这里说的是内部排序。

常用排序算法总结(简单数组实现,其他类似)----- C语言_第1张图片

勘误 : 选择排序是不稳定的 !!!

/*
*
*	各类排序算法复习(简单数组实现,其他类似)
*	Sort Type Review
*	2015.11.09
*	By Snow Yong
*
*/
#define MINIMUMSIZE 7   //快速排序自定义小数组数目
#define A_LENGTH 10   //数组长度
#include 

int Swap(int *a, int i, int j);
int BubbleSort(int *a);
int SelectSort(int *a);
int InsertSort(int *a);
int ShellSort(int *a);
int HeapSort(int *a);
int HeapAdjust(int *a, int low, int high);
int MergeSort(int *a);
int Msort(int *S, int *T, int low, int high);
int Merge(int *S, int *T, int low, int m, int high);
int QuickSort(int *a);
int Qsort(int *a, int low, int high);
int Partition(int *a, int low, int high);
int PickMiddle(int *a, int low, int high);


/*  Swap Function using to swap element
*	元素交换函数	
*/
int Swap(int *a, int i, int j)
{
	int temp;
	
	temp = a[i];
	a[i] = a[j];
	a[j] = temp;
}

//BubbleSort  --  冒泡排序 O(n^2)
int BubbleSort(int *a)
{
	/*	
	*	flag is using for sort flag
	*	flag变量用于提高冒泡效率	
	*/
	int i, j, flag = 1;
	
	for (i = 0; i < A_LENGTH-1  &&  flag; i++)
	{
		flag = 0;//若flag经 j 循环后为0,则说明序列已然有序
		for (j = A_LENGTH-1; j > i; j--)
		{
			if (a[j] < a[j-1])
			{
				Swap(a, j, j-1);
				flag = 1;
			}
		}
	}
}


//SelectSort  --  选择排序 O(n^2)
int SelectSort(int *a)
{
	int i, j, min;
	
	for (i = 0; i < A_LENGTH-1; i++)
	{
		min = i;
		
		for (j = i+1; j < A_LENGTH; j++)
		{
			if (a[min] > a[j])
			{
				min = j;/*不直接交换值,而是记录下标*/
			}
		}
		
		//若下标不同再一次替换成最小值
		if (min != i)
		{
			Swap(a, min, i);
		}
	}
}


//InsertSort  --  插入排序 O(n^2)
int InsertSort(int *a)
{
	int i, j, temp;
	
	//从第二个数开始循环
	for (i = 1; i < A_LENGTH; i++)
	{
		//满足前提的条件下再记录a[i]的值
		if (a[i] < a[i-1])
		{
			temp = a[i];
			
			for (j = i-1;
				a[j] > temp  &&  j >= 0;
				j--)
			{
				a[j+1] = a[j];
			}
			
			a[j+1] = temp;/*此处为a[j+1]而不是a[j]是因为上面循环最后执行了j--*/
		}
	}
}


//ShellSort  --  希尔排序 O(n^(3/2))
int ShellSort(int *a)
{
	int i, j, temp;
	int increament = A_LENGTH;/*类似插入排序,increament增量处理*/
	//跳跃式插入排序
	do
	{
		increament = increament/3 + 1;
		
		for (i = 0+increament; i < A_LENGTH; i++)
		{
			if (a[i] < a[i-increament])
			{
				temp = a[i];
				
				for (j = i-increament;
					a[j] > temp  &&  j >= 0;
					j -= increament)
				{
					a[j+increament] = a[j];
				}
				
				a[j+increament] = temp;
			}
		}
	}
	while (increament > 1);
}


//HeapSort  --  堆排序 O(nlogn)
int HeapSort(int *a)
{
	int i;
	//自行查阅堆和大(小)顶堆的定义
	//初始化从中间位置开始构造大顶堆
	for (i = A_LENGTH/2 - 1; i >= 0; i--)
	{
		HeapAdjust(a, i, A_LENGTH-1);
	}
	
	//此处一边将最大值选出,一边重新从 0 到 i-1 下标调整大顶堆
	for (i = A_LENGTH - 1; i > 0; i--)
	{
		Swap(a, 0, i);
		HeapAdjust(a, 0, i-1);
	}
}

//该函数为堆的调整函数(将序列调整为大顶堆), 核心实现函数
int HeapAdjust(int *a, int low, int high)
{
	int i, j, temp = a[low];
	
	for (i = 2*low + 1; i <= high; i = 2*i + 1)
	{
		if (i < high  &&  a[i] < a[i+1])
		{
			i++;
		}/*左右孩子值比较取其较大者*/
		
		if (temp >= a[i])
		{//父节点值不小于孩子节点值
			break;
		}
		
		a[low] = a[i];
		low = i;/*不断将下标替换较大值的孩子的下标*/
	}
	
	a[low] = temp;
}/*此函数用于调整排序序列为大顶堆*/


//MergeSort  --  归并排序(递归式) O(nlogn),
//非递归的归并算法请参考博文  ”非递归 -- 归并排序(C语言)“ ,注:一般推荐采用非递归的归并算法
int MergeSort(int *a)
{
	Msort(a, a, 0, A_LENGTH-1);
}

int Msort(int *S, int *T, int low, int high)
{
	int m;
	int T_temp[A_LENGTH];/*辅助数组*/
	
	if (S[low] == S[high])
	{
		T[low] = S[low];
	}
	else
	{
		m = (low + high) / 2;
		
		Msort(S, T_temp, low, m);
		Msort(S, T_temp, m+1, high);
		Merge(T_temp, T, low, m, high);
	}
}

int Merge(int *S, int *T, int low, int m, int high)//归并主要实现函数
{
	int j, k, l;/*k用于T数组的下标前进*/
	
	for (k = low, j = m+1;
		low <= m  &&  j <= high;
		k++)
	{
		if (S[low] < S[j])
		{
			T[k] = S[low++];
		}
		else
		{
			T[k] = S[j++];
		}
	}
	
	if (low <= m)
	{
		for (l = 0; l <= m-low; l++)
		{
			T[k+l] = S[low+l];
		}
	}
	
	if (j <= high)
	{
		for (l = 0; l <= high-j; l++)
		{
			T[k+l] = S[j+l];
		}
	}
}



//QuickSort  --  快速排序(已优化) O(nlogn)
int QuickSort(int *a)
{
	Qsort(a, 0, A_LENGTH-1);
}

int Qsort(int *a, int low, int high)
{
	int pivot;/*枢轴值*/
	
	if ((high - low) > MINIMUMSIZE)
	{
		while (low < high)
		{
			pivot = Partition(a, low, high);
			
			Qsort(a, low, pivot-1);
			low = pivot + 1;/*此处优化Qsort(a, pivot+1, high)的尾递归*/
		}
	}
	else/*优化小数组的处理方式 -- 变为插入排序效率更高*/
	{
		InsertSort(a);
	}
}

//此处为求枢轴的函数
int Partition(int *a, int low, int high)
{
	int temp;
	PickMiddle(a, low, high);/*经此函数保证a[low]为较接近中间值*/
	
	temp = a[low];
	
	while (low < high)
	{
		while (low < high  &&  a[high] >= temp)
		{
			high--;
		}
		a[low] = a[high];/*此处优化不必要的交换*/
		
		while (low < high  &&  a[low] <= temp)
		{
			low++;
		}
		a[high] = a[low];/*此处优化不必要的交换*/
	}
	
	a[low] = temp;
	return low;
}

//取接近序列中间大小值并交换给a[low]的函数
int PickMiddle(int *a, int low, int high)
{
	int m = (low + high) / 2;
	
	if (a[low] > a[high])
	{
		Swap(a, low, high);
	}
	if (a[m] > a[high])
	{
		Swap(a, m, high);
	}
	if (a[low] > a[m])
	{
		Swap(a, low, m);
	}
}

int main()
{
	int i;
	int a[A_LENGTH] = {50, 90, 80, 40, 30,
				70, 60, 10, 20, 100};
			
	printf("Before sorting:");
	for (i = 0; i < A_LENGTH; i++)
	{
		printf("%d -- ", a[i]);
	}
	
	// BubbleSort(a);
	// SelectSort(a);
	// InsertSort(a);
	// ShellSort(a);
	// HeapSort(a);
	// MergeSort(a);
	QuickSort(a);
	
	printf("\n\nAfter sorting: ");
	for (i = 0; i < A_LENGTH; i++)
	{
		printf("%d -- ", a[i]);
	}
	return 0;
}

运行结果就不上图了,跟其他排序详解都差不多,因为不喜欢VS卡又慢,所以平台是win + notepad++,编译用的是 MinGW 的 gcc ,因为懒得开虚拟机运行CentOS,
大概结果可参考其他排序算法详解,能力有限,谢谢阅读!

当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序序。
快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;


你可能感兴趣的:(数据结构&常用算法,C语言)