1.概述

  所谓排序, 就是使一串记录, 按照其中的某个或某些关键字的大小, 递增或递减的排列起来的操作。 排序算法, 就是如何使得记录按照要求排列的方法。排序算法在很多领域得到相当地重视, 尤其是在大量数据的处理方面。 一个优秀的算法可以节省大量的资源。 在各个领域中考虑到数据的各种限制和规范,要得到一个符合实际的优秀算法, 得经过大量的推理和分析。
  排序算法稳定性: 假定在待排序的记录序列中, 具有多个相同的元素, 若经过排序, 这些记录的相对次序保持不变, 即在原序列中, r[i]=r[j], 且 r[i]在 r[j]之前, 而在排序后的序列中, r[i]仍在 r[j]之前, 则称这种排序算法是稳定的; 否则称为不稳定的。
  时间复杂度: 即从序列的初始状态到经过排序算法的位置交换处理, 得到最终排序好的结果状态的过程所花费的时间度量。 在计算机科学中, 时间复杂性, 又称时间复杂度, 算法的时间复杂度是一个函数, 它定性描述该算法的运行时间。 这是一个代表算法输入值的字符串的长度的函数。 时间复杂度常用O符号表示。

2.冒泡排序

  冒泡排序实现原理是把较小元素(较大元素)往后调。通过对相邻元素进行两两比较,根据比较结果将两元素位置对调, 最终达到从小到大或者从大到小的顺序。
  冒泡排序的基本思想是: 如按从大到小顺序排序, 将第 1 个元素和第 2 个元素比较,若第 1 个小于第 2 个,则将两个元素位置交换, 反之则不动; 接着再对第 2 个元素和第 3 个元素比较, 若第 2 个小于第 3 个, 则将两个元素位置交换, 反之则不动; 依次类推, 一轮下来则将找到一个最小值放到最末尾。接下来在进行第二轮比较, 则可以找到第二小值放到倒数第二位置, 直到进行 n-1轮比较,即可使数据有序。
  冒泡排序时间复杂度 O(n²)
  冒泡排序是一个稳定的排序算法。

#include <stdio.h>
int main()
{	
	int data[]={4,1,3,6,2,5};
	int i=0,j;
	int temp;
	int count=sizeof(data)/sizeof(int);
	for(i=0;i<count-1;i++)//比较轮数
	{
		for(j=0;j<count-1-i;j++)//每轮比较的次数
		{
			if(data[j]>data[j+1])
			{
				temp=data[j];
				data[j]=data[j+1];
				data[j+1]=temp;
			}
		}
	}
	printf("从小到大:");
	for(i=0;i<count;i++)
	{
		printf("%d ",data[i]);
	}
	printf("\n");
}

2.快速排序

  快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
  (1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
  (2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。
  (3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
  (4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
  快速排序(Quick_sort)是对冒泡排序的一种改进,它也是属于冒泡类的方法。
  快速排序时间复杂度:O(log2n)
  快速排序是一个不稳定的排序算法。

#include <stdio.h>
void quicksort(int *arr,int first,int end);
int main()
{
	int arr[]={3,5,7,1,2,4,6};
	quicksort(arr,0,7-1);
	int i=0;
	for(i=0;i<7;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
	return 0;
}
void quicksort(int *arr,int first,int end)
{
	if(first>=end)return ;
	int i=first;
	int j=end;
	int pivot=arr[i];
	int cnt=0;
	while(1)
	{
		while(arr[i]<=pivot && i<end)i++;//从前往后找大于pivot的数
		while(arr[j]>=pivot && j>first)j--;//从后往前找小于pivot的数据
		if(i>=j)break;
		//交换位置
		int temp=arr[i];
		arr[i]=arr[j];
		arr[j]=temp;
	}
	arr[first]=arr[j];
	arr[j]=pivot;
	quicksort(arr,0,j);//对前半部分排序
	quicksort(arr,j+1,end);//对后半部分排序
}

3.插入排序

  插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。插入排序是一种最简单的排序方法,它的实现原理是将一个元素插入到一个有序列表中。其实现过程可以通过两层循环,外层循环控制有序列表的数量,内层循环是判断新元素,将新元素插入到有序列表中。

  •  时间复杂度:

  在插入排序中,当待排序数组是有序时,此时为最优情况,只需当前数跟前一个数比较一下,这时一共需要比较N- 1次,时间复杂度为O(N)
  最坏的情况是待排序数组是逆序的,此时需要比较次数最多,总次数记为:1+2+3+…+N-1,所以,插入排序最坏情况下的时间复杂度为O(N²)
  插入排序适用于已经有部分数据有序,并且有序数列越大越好。一般在数据规模大于1000的场合下不建议使用插入排序
  插入排序是一个不稳定的排序算法。

#include <stdio.h>
int main()
{
	char buff[]={3,5,7,1,2,64,6};
	int count=sizeof(buff)/sizeof(char);
	int i,j;
	int temp;
	for(i=1;i<count;i++)
	{
		for(j=i;j>0;j--)
		{
			if(buff[j]>buff[j-1])
			{
				temp=buff[j];
				buff[j]=buff[j-1];
				buff[j-1]=temp;
			}
		}
	}
	for(i=0;i<count;i++)
	{
		printf("%d ",buff[i]);
	}
	printf("\n");
}

4.希尔排序

  希尔排序(Shell’s Sort)是插入排序的一种,又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。该方法因 D.L.Shell于1959年提出而得名。
  希尔排序是把要排序的元素进行分组插入排序,把元素的分组数作为循环轮数,分组数量一般设置为log2N(N为成员个数)。每完成一轮,分组数量减半,直到组数为1,即整个元素分成一组,即排序完成。
  希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比O(N²)好一些。
  希尔排序是一个稳定的排序算法。

#include <stdio.h>
void shellSort(int *arr,int count)
{
	int gap=0;
	int temp;
	int i=0,j=0;
	for(gap=count>>1;gap>0;gap>>=1)
	{
		for(i=gap;i<count;i++)
		{
			temp=arr[i];
			j=i-gap;
			while(j>=0 && arr[j]<temp)
			{
				arr[j+gap]=arr[j];
				j-=gap;
			}
			arr[j+gap]=temp;
		}
	}
}
int main()
{
	int arr[]={1,2,3,4,5,6,7,8};
	int count=sizeof(arr)/sizeof(int);
	shellSort(arr,count);
	printf("从大到小排序:\n");
	for(int i=0;i<count;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

5.选择排序

  选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
  选择排序时间复杂度都是O(n²)
  选择排序是一个不稳定的排序算法。

void SelectSort(int *arr,int count)
{
	int i,j;
	int temp;
	int min;
	for(i=0;i<count-1;i++)
	{
		min=i;
		for(j=i+1;j<count;j++)
		{
			//找到最小的下下标
			if(arr[j]<arr[min])min=j;
		}
		temp=arr[i];
		arr[i]=arr[min];
		arr[min]=temp;
	}
}
void main(){
	int arr[] = {6,4,8,9,2,3,1,0};
	int count=sizeof(arr)/sizeof(int);
	SelectSort(arr,count);
	int i=0;
	printf("排序结果:");
	for(i=0;i<count;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}