本文介绍几种常用的排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序。
冒泡排序
冒泡排序(Bubble Sort):它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
实例:
#include void bubble_sort(int [],int);int main(){int i;int arr[]={22,34,3,32,82,55,89,50,37,5,64,35,9,70}; int len=(int)sizeof(arr)/sizeof(*arr); bubble_sort(arr,len); for(i=0;i<len;i++) printf("%d ",arr[i]); return 0;}void bubble_sort(int arr[],int len){ int i,j,temp; for(i=0;i<len-1;i++) for(j=0;jarr[j+1]){ temp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; }}
运行结果:
3 5 9 22 32 34 35 37 50 55 64 70 82 89
选择排序
选择排序(Selection Sort):首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
实例:
#include void selection_sort(int [],int);int main(){int i;int arr[]={22,34,3,32,82,55,89,50,37,5,64,35,9,70}; int len=(int)sizeof(arr)/sizeof(*arr); selection_sort(arr,len); for(i=0;i<len;i++) printf("%d ",arr[i]); return 0;}void selection_sort(int a[],int len) { int i,j,temp; for(i=0;i<len-1;i++) { int min=i; // 记录最小值,第一个元素默认最小 for(j=i+1;j<len;j++)// 访问未排序的元素 { if(a[j]<a[min])// 找到目前最小值 min=j;// 记录最小值 } if(min!=i) { temp=a[min];// 交换两个变量 a[min]=a[i]; a[i]=temp; } }}
运行结果:
3 5 9 22 32 34 35 37 50 55 64 70 82 89
插入排序
插入排序(英语:Insertion Sort):通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序,因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
实例:
#include void insertion_sort(int [],int);int main(){int i;int arr[]={22,34,3,32,82,55,89,50,37,5,64,35,9,70}; int len=(int)sizeof(arr)/sizeof(*arr); insertion_sort(arr,len); for(i=0;i<len;i++) printf("%d ",arr[i]); return 0;}void insertion_sort(int arr[],int len){ int i,j,temp; for(i=1;i0&&arr[j-1]>temp;j--) arr[j]=arr[j-1]; arr[j]=temp; }}
运行结果:
3 5 9 22 32 34 35 37 50 55 64 70 82 89
希尔排序
希尔排序(Shell Sort):也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
- 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率
- 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位
实例
#include void shell_sort(int [],int);int main(){int i;int arr[]={22,34,3,32,82,55,89,50,37,5,64,35,9,70}; int len=(int)sizeof(arr)/sizeof(*arr); shell_sort(arr,len); for(i=0;i>1;gap>0;gap=gap>>1) for(i=gap;i=0&&arr[j]>temp;j-=gap) arr[j+gap]=arr[j]; arr[j+gap]=temp; }}
运行结果:
3 5 9 22 32 34 35 37 50 55 64 70 82 89
归并排序
归并排序(Merge Sort):把数据分为两段,从两段中逐个选最小的元素移入新数据段的末尾。
可从上到下或从下到上进行。
实例迭代法
#include #include int mini(int,int);void merge_sort(int [],int);int main(){int i;int arr[]={22,34,3,32,82,55,89,50,37,5,64,35,9,70}; int len=(int)sizeof(arr)/sizeof(*arr); merge_sort(arr,len); for(i=0;i<len;i++) printf("%d ",arr[i]); return 0;}int mini(int x,int y) { return x<y?x:y;}void merge_sort(int arr[],int len){ int *a=arr; int *b=(int*)malloc(len*sizeof(int));int *temp,seg,start; for(seg=1;seg<len;seg+=seg){ for(start=0;start<len;start+=seg+seg){ int low=start;int mid=mini(start+seg,len);int high=mini(start+seg+seg,len); int k=low; int start1=low;int end1=mid; int start2=mid;int end2=high; while(start1<end1&&start2<end2) b[k++]=a[start1]<a[start2]?a[start1++]:a[start2++]; while(start1<end1) b[k++]=a[start1++]; while(start2<end2) b[k++]=a[start2++]; } temp=a; a=b; b=temp; } if(a!=arr){ int i; for(i=0;i<len;i++) b[i]=a[i]; b=a; } free(b);}
递归法
#include #include #define N 14void merge_sort_recursive(int [],int [],int,int);void merge_sort(int [],const int);int main(){int i;int arr[]={22,34,3,32,82,55,89,50,37,5,64,35,9,70}; int len=(int)sizeof(arr)/sizeof(*arr); merge_sort(arr,len); for(i=0;i=end) return; len=end-start;mid=(len>>1)+start; start1=start;end1=mid; start2=mid+1;end2=end; merge_sort_recursive(arr,reg,start1,end1); merge_sort_recursive(arr,reg,start2,end2); k=start; while(start1<=end1&&start2<=end2) reg[k++]=arr[start1]<arr[start2]?arr[start1++]:arr[start2++]; while(start1<=end1) reg[k++]=arr[start1++]; while(start2<=end2) reg[k++]=arr[start2++]; for(k=start;k<=end;k++) arr[k]=reg[k];}void merge_sort(int arr[], const int len){ int reg[N]; merge_sort_recursive(arr,reg,0,len-1);}
运行结果:
3 5 9 22 32 34 35 37 50 55 64 70 82 89
备注:常用排序算法的时间复杂度和空间复杂度