[演算法] 排序演算法總結
阿新 • • 發佈:2021-09-19
總述
借圖侵刪
SHELL排序
時間複雜度:O(N^(X)) (X<=2)
又稱“縮小增量排序”,是插入排序的進化版,其高效之處在於通過增量間隔的比較和交換,比樸素的插入排序減少了交換次數,從而提高了效率。感性認知來講,確實可以提高演算法效率,但是我不會證明該演算法的時間複雜度。
1 void Shell_sort(int l, int r) 2 { 3 int gap = r - l + 1; 4 int tep = 0; 5 do 6 { 7 gap = gap / 3 + 1; 8 for (inti = l + gap; i <= r; ++i) 9 { 10 if (a[i - gap] > a[i]) 11 { 12 tep = a[i]; 13 int j = i - gap; 14 do 15 { 16 a[j + gap] = a[j]; 17 j -= gap; 18 } while(j >= l && a[j] > tep); 19 a[j + gap] = tep; 20 } 21 } 22 }while (gap > 1); 23 }
歸併排序
時間複雜度:O(N*logN)
分治的思想+O(N)合併有序陣列。
22 void GB_sort(int l, int r) 23 { 24 if (l == r) return; 25 int mid = (l + r) >> 1; 26 GB_sort(l, mid), GB_sort(mid + 1, r); 27 int t1 = l, t2 = mid + 1, t3 = l; 28 for (int i = l; i <= r; ++i) 29 if ((a[t1] <= a[t2] && t1 <= mid) || t2 == r + 1) b[t3] = a[t1], ++t1, ++t3; 30 else b[t3] = a[t2], ++t2, ++t3; 31 for (int i = l; i <= r; ++i) 32 a[i] = b[i]; 33 }
堆排序
時間複雜度:O(N*logN)
本質上就是維護一個大根堆。也是選擇排序的一種。
注意堆的初始化要自下而上!因為update函式是自上而下更新的,向下可以保證操作到位,而向上無法進行。
1 void update(int x, int m) 2 { 3 int t = lson(x); 4 if (t > m) return; 5 if (t < m && a[t + 1] > a[t]) ++t; 6 if (a[t] > a[x]) swap(a[x], a[t]); 7 update(t, m); 8 } 9 10 void HEAP_sort() 11 { 12 for (int i = n; i >= 1; --i) 13 update(i, n); 14 for (int i = n - 1; i >= 1; --i) // 每次取出最大值並維護堆 15 { 16 swap(a[i + 1], a[1]); 17 update(1, i); 18 } 19 }
快速排序
時間複雜度:平均O(N*logN)
交換排序的一種,具體流程如下:
選擇基準值---將小於基準值的值置於基準值之前,將大於基準值的值置於基準值之後---遞迴
不難看出這個演算法是很容易被卡成N^2的,故手寫時應至少加一個隨機化(雖然很少去手寫)。
1 void Quick_sort(int l, int r) 2 { 3 if (l >= r) return; 4 int i = l, j = r; 5 int x = a[i]; 6 while (i < j) 7 { 8 while (i < j && a[j] > x) --j; 9 if (i < j) a[i++] = a[j]; 10 while (i < j && a[i] < x) ++i; 11 if (i < j) a[j--] = a[i]; 12 } 13 a[i] = x; 14 Quick_sort(l, i - 1); 15 Quick_sort(i + 1, r); 16 return; 17 }
所以為什麼快速排序叫做快排?手寫起來慘不忍睹還會被卡