選擇類排序包括:
(1) 簡單選擇排序
(2)樹形選擇排序
(3)堆排序
簡單選擇排序:
【算法思想】:在第 i 趟簡單選擇排序中,從第 i 個記錄開始,通過 n - i 次關鍵字比較,從 n - i + 1 個記錄中選出關鍵字最小的記錄,並和第 i 個記錄進行交換
時間復雜度:O(n^2)
1 //此函數中a[0]不用,即對 a[1] ~ a[length-1] 排序;
//如果對a[0]~a[length-1]排序,將 for 循環中的 i = 1 改為 i = 0 即可,注意輸出
2 void select(int a[],int length){//length為數組的長度
3 int i,j; 4 int min;//記錄最小值的位置
5
6 for(i = 1;i < length - 1;i++){ 7 min = i; 8 //選擇最小的值
9 for(j = i + 1;j < length;j++){ 10 if(a[j] < a[min]) //更新最小值的坐標
11 min = j; 12 } 13 if(min != i){ 14 int temp; 15 temp = a[min]; 16 a[min] = a[i]; 17 a[i] = temp; 18 } 19 } 20 }
堆排序:
堆排序是威洛母斯在1964年提出的對樹形選擇排序的改進算法,其只需要一個記錄大小的輔助空間,采用向量數組方式存儲,采用完全二叉樹的順序結構的特征進行分析,而非采用樹的存儲結構。
從小到大排序采用大根(頂)堆:r[i].key >= r[2i].key && r[i].key >= r[2i+1].key (結點值大於等於其左子與右子)
從大到小排序采用小根(頂)堆:r[i].key <= r[2i].key && r[i].key<= r[2i+1].key (結點值小於等於其左子與右子)
【算法思想】把待排序的記錄的關鍵字存放在數組 r[1...n] 中,將 r 看成一棵完全二叉樹的順序表示,每個結點表示一個記錄,第一個記錄 r[1] 作為二叉樹的根,以下各記錄 r[2] ~ r[n] 依次逐層從左到右順序排列,任意結點 r[i] 的左孩子是 r[2i] ,右孩子是 r[2i+1],雙親是 r[i/2]。對這棵二叉樹進行調整建堆。
時間復雜度:O(nlog2n)
說明:在c語言中,i/2 的含義是整除,不同於數學中的定義,即 3/2 = 1,有一個向下取整的意思
堆排序可分為2步(從小到大排序):
<1> 建初堆:建立一個大根堆
<2>重建堆:進行 n - 1 趟的交換(r[1] 與 堆尾進行交換)和建堆的過程
1 /*堆排序*/
2 /*建初堆:大根堆*/
3 void AdjustDown(int a[],int k,int len); 4 void BuildMaxHeap(int a[],int len){ 5 int i; 6 for(i = len/2;i > 0;i--){ 7 AdjustDown(a,i,len); 8 } 9 } 10 //調整堆
11 void AdjustDown(int a[],int k,int len){ 12 a[0] = a[k];//將第一個記錄移出
13 int i; 14 for(i = 2*k;i <= len;i = 2*i){ 15 if(i < len && a[i] < a[i+1])//不能忘記i < len,否則會超出范圍
16 i++;//取左右子中的最大值
17 if(a[0] >= a[i]) 18 break; 19 else{ 20 a[k] = a[i]; //將a[i]調整到其雙親結點上
21 k = i; //修改k值,以便繼續向下篩選
22 } 23 } 24 a[k] = a[0]; 25 } 26
27 void HeapSort(int a[],int len){ 28 BuildMaxHeap(a,len); 29 int i; 30 int temp; 31 for(i = len;i > 1;i--){ 32 //第一個和堆尾進行交換
33 temp = a[1]; 34 a[1] = a[i]; 35 a[i] = temp; 36 //調整堆
37 AdjustDown(a,1,i-1); 38 } 39 }
圖可參照:https://blog.csdn.net/u013384984/article/details/79496052
測試:
1 int main(){ 2 int a[11] = {-1,2,3,1,4,7,3,5,1,6,0}; 3 int b[11] = {-1,2,3,1,4,7,3,5,1,6,0}; 4 int i,j; 5 select(a,11); //沒有用a[0],對后面的元素進行排序
6 HeapSort(b,10);//數組的最后一個下標,a[0]為輔助單元
7 for ( i = 1;i < 11;i++){ 8 printf("%d \t",a[i]); 9 } 10 printf("\n"); 11
12 for ( i = 1;i < 11;i++){ 13 printf("%d \t",b[i]); 14 } 15 printf("\n"); 16 }