三种排序比较
1.冒泡排序
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
算法描述
- 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
- 针对所有的元素重复以上的步骤,除了最后一个;
- 重复步骤1~3,直到排序完成。
#include<stdio.h> #include<time.h> #include<stdlib.h> #define N 10000 int a[N]; void bubblesort(int); void swap(int,int); int main(void) { int i,n; scanf("%d",&n); srand((unsigned)time(NULL)); for(i=0;i<n;i++) { a[i]=rand()%100; printf("%d ",a[i]); } printf("\n"); bubblesort(n); for(i=0;i<n;i++) printf("%d ",a[i]); printf("\n"); return 0; } void bubblesort(int num) { int i,j; for(i=0;i<num-1;i++) for(j=0;j<num-i-1;j++) { if(a[j]>a[j+1]) swap(j+1,j); } return; } void swap(int i,int j) { int temp; temp=a[i]; a[i]=a[j]; a[j]=temp; return; }
冒泡排序平均时间复杂度
O(n2).
注意:冒泡排序每排一次得到最大值,最小值慢慢往左移
2.快速排序
快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
算法描述
快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:
- 从数列中挑出一个元素,称为 “基准”(pivot);
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
#include<stdio.h> #include<time.h> #include<stdlib.h> #define N 10000 int a[N]; void quicksort(int,int); int partition(int,int); void swap(int,int); int main(void) { int i,n; scanf("%d",&n); srand((unsigned)time(NULL)); for(i=0;i<n;i++) { a[i]=rand()%100; printf("%d ",a[i]); } printf("\n"); quicksort(0,n-1); for(i=0;i<n;i++) printf("%d ",a[i]); printf("\n"); return 0; } void quicksort(int low,int high) { if(low<high) { int i; i=partition(low,high); quicksort(low,i-1); quicksort(i+1,high); } return; } int partition(int low,int high) { int i,j,pivot; i=low; j=high; pivot=a[low]; while(i<j) { while(i<j&&a[j]>=pivot) j--; while(i<j&&a[i]<=pivot) i++; if(i<j) swap(i,j); } swap(low,i); return i; } void swap(int i,int j) { int temp; temp=a[i]; a[i]=a[j]; a[j]=temp; return; }
partiton(int,int)每次找出一个基值,在基值左边的数都小于基值,右边的数大于基值。
在quicksort(int)递归地分别排序
平均时间复杂度O(nlogn)
3.归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
#include<stdio.h> #include<time.h> #include<stdlib.h> #define N 10000 int a[N]; void mergesort(int,int); void merge(int,int,int); int main(void) { int i,n; scanf("%d",&n); srand((unsigned)time(NULL)); for(i=0;i<n;i++) { a[i]=rand()%100; printf("%d ",a[i]); } printf("\n"); mergesort(0,n-1); for(i=0;i<n;i++) printf("%d ",a[i]); printf("\n"); return 0; } void mergesort(int low,int high) { if(low<high) { int mid=(high-low)/2+low; mergesort(low,mid); mergesort(mid+1,high); merge(low,mid,high); } return; } void merge(int low,int mid,int high) { int i=low; int j=mid+1; int k=0; int *tmp; tmp=(int*)malloc((high-low+1)*sizeof(int)); while(i<=mid&&j<=high) (a[i]>a[j])?(tmp[k++]=a[j++]):(tmp[k++]=a[i++]); while(i<=mid) tmp[k++]=a[i++]; while(j<=high) tmp[k++]=a[j++]; for(k=0,i=low;i<=high;k++,i++) a[i]=tmp[k]; free(tmp); return; }
平均时间复杂度O(nlogn)
需要分配动态空间