什麼是雙調排序法?
雙調排序法是一種使用「雙調序列」的排序演算法,先將資料分割成遞增與遞減兩段,再透過合併步驟將它們轉成完整排序序列。
雙調序列
雙調序列由一段遞增和一段遞減序列組成,像是一個菱形或山形,稱為 bitonic sequence。
演算法步驟
- 把陣列分成兩個子序列,一個升冪、一個降冪。
- 對兩個子序列遞迴進行雙調排序。
- 執行雙調合併,將雙調序列整理成完全排序結果。
特性
- 平行友善:非常適合硬體加速或 SIMD 平行運算。
- 穩定性:演算法本身非穩定排序。
- 空間:主要使用遞迴和少量額外空間。
- 適合規格:在需要可預測比較步驟的情境中表現良好。
虛擬碼與實際程式碼對照
下方比較展示了雙調排序法的關鍵步驟與對應的 JavaScript 實作,讓演算法概念與程式流程更直觀。
虛擬碼
function bitonicSort(start, count, direction):
if count <= 1:
return
mid = count / 2
bitonicSort(start, mid, ASCENDING)
bitonicSort(start + mid, mid, DESCENDING)
bitonicMerge(start, count, direction)
function bitonicMerge(start, count, direction):
if count <= 1:
return
k = count / 2
for i in start .. start + k - 1:
compareAndSwap(i, i + k, direction)
bitonicMerge(start, k, direction)
bitonicMerge(start + k, k, direction)
實際 JavaScript 對照
async function bitonicSort(start, count, direction) {
if (count <= 1 || !isSorting) return;
const mid = Math.floor(count / 2);
await bitonicSort(start, mid, 1);
await bitonicSort(start + mid, count - mid, 0);
await bitonicMerge(start, count, direction);
}
async function bitonicMerge(start, count, direction) {
if (count <= 1 || !isSorting) return;
const k = Math.floor(count / 2);
for (let i = start; i < start + k; i++) {
await compareAndSwap(i, i + k, direction);
}
await bitonicMerge(start, k, direction);
await bitonicMerge(start + k, count - k, direction);
}
程式碼與動畫對應
if (count <= 1 || !isSorting) return; -> 無須排序或已取消時停止,動畫不再繼續
const mid = Math.floor(count / 2); -> 計算分割點,準備將區段分為上下兩部份
await bitonicSort(start, mid, 1); -> 遞迴建立升冪子序列,動畫呈現左側遞迴處理
await bitonicSort(start + mid, count - mid, 0); -> 遞迴建立降冪子序列,動畫呈現右側遞迴處理
await bitonicMerge(start, count, direction); -> 執行合併,動畫開始比較與交換成有序序列
await compareAndSwap(i, i + k, direction); -> 比較成對元素並在動畫中交換位置