面试必备:排序算法汇总(c++实现)
排序算法主要考点: 7种排序
冒泡排序、选择排序、插入排序、shell排序、堆排序、快速排序、归并排序
以上排序算法是面试官经常会问到的算法,至于其他排序比如基数排序等等,这里不列举。
以下算法通过c++实现,开发工具Visual Studio 2012:代码下载
一、排序 :将杂乱无章的数据元素,通过一定的方法按关键字顺序排列的过程
排序分为内部排序、外部排序;
若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。
反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序
假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,
即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;
否则称为不稳定的。
1. 冒泡排序
时间复杂度:最好的情况:表本身就是有序的,n-1次比较,时间复杂度为O(n);最坏的情况:表是逆序的,此时需要比较 1+2+3+...(n-1) = (n(n-1))/2,时间复杂度为O(n2)
优点:简单、稳定
缺点:慢,每次只能移动相邻两个数据,效率低
c++实现:
1 //冒泡排序 2 void Bubble_Sort(int *list,int count) 3 { 4 int flag = true; 5 int i = 0,j = 0; 6 for(i=0;i<=count&&flag;i++) 7 { 8 flag = false; 9 for(j=count -1;j>=i;j--) 10 { 11 if(list[j]<list[j-1]) 12 { 13 swap(list[j],list[j-1]); 14 flag = true; 15 } 16 } 17 } 18 19 }
2. 选择排序
时间复杂度:O(n2) :无论最好、最坏情况,都需要比较 (n(n-1))/2次,最好的情况交换次数为0,最坏的情况交换次数为n-1
优点:交换移动数据次数相当少,性能上略优于冒泡排序
缺点:效率低
c++实现:
1 //选择排序 2 void Select_Sort(int *list,int count) 3 { 4 int min,i,j; 5 for(i=0;i<count;i++) 6 { 7 min = i; 8 for(j=i+1;j<count;j++) 9 { 10 if(list[i]>list[j]) 11 { 12 min = j; 13 } 14 } 15 if(min!=i) 16 { 17 swap(list[i],list[min]); 18 } 19 20 } 21 }
3. 插入排序
时间复杂度:最好情况:表本身就是有序的,比较次数是n-1次,没有移动记录,时间复杂度为O(n);最坏情况:表本身是无序的,比较次数是2+3+4+...+n = (n+2)(n-1)/2,移动次数也达到最大
值为 (n+4)(n-1)/2次,所以时间复杂度为O(n2);如果根据概论相同的原则,平均比较和移动次数约为n2/4;
优点:比选择,冒泡排序性能要好一些
缺点:效率较低
c++实现:
1 //插入排序 2 void Insert_Sort(int *list,int count) 3 { 4 int temp;/*此处充当哨兵,不在list数组里面单独占一个单位*/ 5 int i,j; 6 for(i=1;i<count;i++) 7 { 8 if(list[i]<list[i-1]) 9 { 10 temp = list[i]; 11 for(j=i-1;list[j]>temp&&j>=0;j--) 12 { 13 list[j+1] = list[j]; 14 } 15 list[j+1] = temp; 16 } 17 } 18 }
4. shell排序
时间复杂度:O(n3/2)
优点:跳跃式移动,使得排序效率提高
缺点:不是一种稳定的排序算法
c++实现:
1 //shell排序 2 void Shell_Sort(int *list,int count) 3 { 4 int i,j; 5 int temp; 6 int increment = count; 7 do 8 { 9 increment = increment/3+1; 10 for(i = increment;i<count;i++) 11 { 12 if(list[i]<list[i-increment]) 13 { 14 temp = list[i]; 15 for(j=i-increment;j>=0&&list[j]>temp;j-=increment) 16 { 17 list[j+increment] = list[j]; 18 } 19 list[j+increment] = temp; 20 21 } 22 23 } 24 25 }while(increment>1); 26 }
5. 堆排序
时间复杂度:O(nlogn)
优点:性能上远远超过冒泡、选择、插入的时间复杂度O(n2)
缺点:不是一种稳定的排序算法
c++实现:
//调整为一个堆 void Heap_Adjust(int *list,int s,int m) { int temp = list[s]; for(int j=2*s+1;j<=m;j = 2*j+1) { if(list[j]<list[j+1]&&j<m) { j++; } if(temp>list[j]) break; list[s] = list[j]; s = j; } list[s] = temp; } //堆排序 void Heap_Sort(int *list,int len) { //创建一个大顶堆 for(int s = len/2-1;s>=0;s--) { Heap_Adjust(list,s,len-1); } //排序 for(int i = len-1;i >= 1;i--) { swap(list[0],list[i]); Heap_Adjust(list,0,i-1); } }
6. 归并排序
时间复杂度:O(nlogn)
优点:效率高、稳定
缺点:占用内存较多
c++实现:
//将有个有序数组排序 void Merge(int *list,int start,int mid,int end) { const int len1 = mid -start +1; const int len2 = end -mid; const int len = end - start +1; int i,j,k; int * front = (int *)malloc(sizeof(int)*len1); int * back = (int *)malloc(sizeof(int)*len2); for(i=0;i<len1;i++) front[i] = list[start+i]; for(j=0;j<len2;j++) back[j] = list[mid+j+1]; for(i=0,j=0,k=start;i<len1&&j<len2&&k<end;k++) { if(front[i]<back[j]) { list[k] = front[i]; i++; }else { list[k] = back[j]; j++; } } while(i<len1) { list[k++] = front[i++]; } while(j<len2) { list[k++] = back[j++]; } }
//归并排序 void Merge_Sort(int *list,int count) { MSort(list,0,count-1); }
//归并排序 void MSort(int *list,int start,int end) { if(start<end) { int mid = (start+end)/2; MSort(list,0,mid); MSort(list,mid+1,end); Merge(list,start,mid,end); } }
7. 快速排序
时间复杂度:O(nlogn)(平均情况)
优点:目前来说最快的排序算法,现在的快排算法大多是快速排序算法的改进算法
缺点:跳跃式,不稳定
c++实现:
//快速排序 void Quick_Sort(int *list,int count) { Qsort(list,0,count-1); }
//快速排序 void Qsort(int *list,int low,int high) { int pivot; if(low<high) { pivot =Partition(list,low,high); Qsort(list,low,pivot-1); Qsort(list,pivot+1,high); } }
int Partition(int *list,int low,int high) { int pivotKey; pivotKey = list[low]; while(low<high) { while(low<high&&list[high]>=pivotKey) { high--; } swap(list[low],list[high]); while(low<high&&list[low]<=pivotKey) { low++; } swap(list[low],list[high]); } return low; }
附:
void swap(int& a,int& b) { int temp = a; a = b; b = temp; }
总结:排序: 插入排序类: 插入排序,希尔排序
选择排序类: 选择排序,堆排序
交换排序类: 冒泡排序,快速排序
归并排序类: 归并排序