Merge sort 合併排序法
Merge sort 合併排序法
複雜度
複雜度 | Big O |
---|---|
最差時間複雜度 Worst-case time complexity | Big O(n log n) |
平均時間複雜度 Average-case time complexity | Big theta (n log n) |
最佳時間複雜度 Best-case time complexity | Big omega (n log n) |
空間複雜度 Space complexity | Big O (n) |
演算法
1. 建立儲存最後排序結果陣列
會持續比較陣列數字的大小,然後將找到的最小數字儲存在結果陣列
2. 比較兩個最小的排序陣列
將數字陣列不斷地切割,直到切割到剩下最後一個數字陣列,然後往上遞迴比較
持續比較兩個已排序陣列,然後比較兩個排序陣列中最小的數字,加入到最後的排序結果陣列
3. 加入剩餘尚未比較陣列
兩陣列比較完,避免其中一個陣列比完了,但另外一個陣列還有數字還沒比完
因為兩個都是已排序的陣列,所以剩餘陣列的數字一定是比已加入的數字大
所以就直接將剩餘數字的陣列數字,依序地加入到結果陣列中
4. 陣列往上遞迴合併
比較好的新陣列,也會是排序好的陣列,往上回傳後,持續和其他切割的陣列做比較
最後持續這個步驟,會得到一個完整排序後的陣列
程式
JavaScript
function merge(numberList1, numberList2) {
// 最後比較結果陣列
var finalOrderNumberList = [];
// 陣列 1 比較數量
var numberList1Counter = 0;
// 陣列 2 比較數量
var numberList2Counter = 0;
// 比較兩個數字陣列,直到其中一個陣列比較完畢
while (numberList1Counter < numberList1.length && numberList2Counter < numberList2.length) {
if (numberList1[numberList1Counter] < numberList2[numberList2Counter]) {
// 「陣列 1 的數字」比「陣列 2 的數字」小,將「陣列 1 的數字」加到結果陣列
finalOrderNumberList.push(numberList1[numberList1Counter]);
// 陣列 1 繼續比較下一個
numberList1Counter++;
}
else {
// 「陣列 2 的數字」比「陣列 1 的數字」小,將「陣列 2 的數字」加到結果陣列
finalOrderNumberList.push(numberList2[numberList2Counter]);
// 陣列 2 繼續比較下一個
numberList2Counter++;
}
}
// 處理剩餘數字
while (numberList1Counter < numberList1.length) {
// 如果「陣列 1 的數字」還有剩,將所有陣列 1 數字加到結果陣列
finalOrderNumberList.push(numberList1[numberList1Counter]);
numberList1Counter++;
}
while (numberList2Counter < numberList2.length) {
// 如果「陣列 2 的數字」還有剩,將所有陣列 2 數字加到結果陣列
finalOrderNumberList.push(numberList2[numberList2Counter]);
numberList2Counter++;
}
return finalOrderNumberList;
}
function mergeSort(sortNumberList) {
if (sortNumberList.length <= 1) {
// 如果只有 1 個數字,不用排序,直接回傳
return sortNumberList;
}
// 取得中間切割點
var middlePointer = Math.floor(sortNumberList.length / 2);
// 計算切割點左方排序
var leftPartitionOrderNumberList = mergeSort(sortNumberList.slice(0, middlePointer));
// 計算切割點右方排序
var rightPartitionOrderNumberList = mergeSort(sortNumberList.slice(middlePointer));
// 合併兩個排序陣列
return merge(leftPartitionOrderNumberList, rightPartitionOrderNumberList);
}
console.log(mergeSort([70, 50, 30, 10, 20, 40, 60]));
TypeScript
function merge(numberList1: number[], numberList2: number[]): number[] {
// 最後比較結果陣列
let finalOrderNumberList = [];
// 陣列 1 比較數量
let numberList1Counter = 0;
// 陣列 2 比較數量
let numberList2Counter = 0;
// 比較兩個數字陣列,直到其中一個陣列比較完畢
while (numberList1Counter < numberList1.length && numberList2Counter < numberList2.length) {
if (numberList1[numberList1Counter] < numberList2[numberList2Counter]) {
// 「陣列 1 的數字」比「陣列 2 的數字」小,將「陣列 1 的數字」加到結果陣列
finalOrderNumberList.push(numberList1[numberList1Counter]);
// 陣列 1 繼續比較下一個
numberList1Counter++;
} else {
// 「陣列 2 的數字」比「陣列 1 的數字」小,將「陣列 2 的數字」加到結果陣列
finalOrderNumberList.push(numberList2[numberList2Counter]);
// 陣列 2 繼續比較下一個
numberList2Counter++;
}
}
// 處理剩餘數字
while (numberList1Counter < numberList1.length) {
// 如果「陣列 1 的數字」還有剩,將所有陣列 1 數字加到結果陣列
finalOrderNumberList.push(numberList1[numberList1Counter]);
numberList1Counter++;
}
while (numberList2Counter < numberList2.length) {
// 如果「陣列 2 的數字」還有剩,將所有陣列 2 數字加到結果陣列
finalOrderNumberList.push(numberList2[numberList2Counter]);
numberList2Counter++;
}
return finalOrderNumberList;
}
function mergeSort(sortNumberList: number[]): number[] {
if (sortNumberList.length <= 1){
// 如果只有 1 個數字,不用排序,直接回傳
return sortNumberList;
}
// 取得中間切割點
let middlePointer = Math.floor(sortNumberList.length / 2);
// 計算切割點左方排序
let leftPartitionOrderNumberList = mergeSort(sortNumberList.slice(0, middlePointer));
// 計算切割點右方排序
let rightPartitionOrderNumberList = mergeSort(sortNumberList.slice(middlePointer));
// 合併兩個排序陣列
return merge(leftPartitionOrderNumberList, rightPartitionOrderNumberList);
}
console.log(mergeSort([70, 50, 30, 10, 20, 40, 60]));