排序——快排+歸併排序 簡述
阿新 • • 發佈:2021-01-05
排序
快排是不穩定的,歸併是穩定的
快速排序 主要思想:分治(分界點從數組裡隨機取一個點
主要流程
-
確定分界點
- 第一種方法:取左邊界 q[ I ]
- 第二種方式:取中間值 q[ ( 1 + r) / 2]
- 第三種方式 取右邊界 q[ r ]
-
調整區間
使第一個區間裡的數都 小於等於 x (左半邊
第二個區間裡的數都 大於等於 x (右半邊
-
遞迴處理左右兩端
左邊排好序,右邊排好序
第二步中兩個小方法
方法一:
-
設兩個陣列 a[ ] b[ ]
-
檢查q[ l~r ]的數值
- 小於等於X的插到a[ ]裡
- 大於等於X的插到b[ ]裡
-
分別將a[ ]、b[ ]插到q[ ]的第一區間和第二區間
方法二:
- 設定兩個指標low和high,他們的初值分別為s和t。首先將X移至臨時變數,之後檢測指標high所指記錄,若q[ high ] 大於 X,則high減1,否則將q[ high ] 移至指標low所指向的位置;之後檢查指標low所指記錄,若q[ low ] 小於 X ,則 low 增 1,否則將q[ low ] 移至指標high所指位置;重複上述兩個方向的檢測,直到high和low指標指向同一位置
void quick_sort(int q[], int l, int r) { if (l >= r) return; int i = l - 1, j = r + 1, x = q[l + r >> 1]; while (i < j) { do i ++ ; while (q[i] < x); do j -- ; while (q[j] > x); if (i < j) swap(q[i], q[j]); } quick_sort(q, l, j), quick_sort(q, j + 1, r); }
歸併排序 主要思想:分治(以中間點為分解點) (分治方法和快排不同
主要流程
- 確定分界點 : mid = (1 + r) / 2 (左右兩邊的平均值,就是最中間的位置
- 遞迴排序 left(第一個序列) 和 right (第二個序列)
- 歸併 --》 把兩個有序的陣列合二為一 此步驟的時間複雜度是O(n)
如何歸併
首先通過遞迴排序保證兩個序列都是有序的,設定一個新的陣列res[ ] ,和兩個指標分別指向兩個序列的最小值。比較兩個指標指向的數值,把較小的指標指向的數值儲存到res[ ] 中,然後把這個指標後移一位(再次指向此序列中最小值),繼續比較兩指標指向的數值,然後放到陣列res[ ] 中。迴圈往復重複此操作,直至排序成功。
(如果兩個指標指向的數值相等,優先把第一個序列中的數值存到res中,這樣能保證排序是穩定的
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
時間複雜度
平均的快排 和 歸併排序 的時間複雜度都是 nlog2n