排序算法主要考點: 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; }
總結:排序: 插入排序類: 插入排序,希爾排序
選擇排序類: 選擇排序,堆排序
交換排序類: 冒泡排序,快速排序
歸並排序類: 歸並排序