javascript數據結構與算法--歸併排序

歸併排序採用了分治策略,在對數組進行排序的時候,先將數組分割成更小的子數組,而後對子數組排序,最後排序後的子數組合併成一個完成的數組,在對子數組排序的時候能夠使用相同的策略繼續對子數組進行分割,直到子數組中只包含一個元素。
例如咱們須要數組[3,2,6,4,8,1,7,5]排序,首先將數組分割成只包含單個元素的子數組:數組

[3] [2]  [6] [4]  [8]  [1]  [7]  [5]

將相鄰的兩個子數組合並,獲得包含兩個元素的已排序子數組:函數

[2, 3]   [4, 6]  [1, 8]  [5, 7]

繼續兩兩合併:spa

[2, 3, 4, 6]  [1, 5, 7, 8]

最終就能夠獲得一個完成的排序好的數組了:3d

[1, 2, 3, 4, 5, 6, 7, 8]

下面看一下怎麼用JS代碼實現一個歸併排序。
首先看一下怎麼合併兩個已排序的子數組,代碼以下:code

/**
 * 輔助方法,合併數組arr中的兩個已排序的子數組
 * 做爲例子只考慮從小到大排序,其餘排序可自定義比較函數,相似於Array#sort
 * @param {*} arr 數組
 * @param {*} start 起始位置
 * @param {*} end 結束位置(包含在範圍內)
 * @param {*} mid 兩個子數組的分割位置
 */
function merge(arr, start, end, mid) {
 // 須要合併的元素個數
 const count = end - start + 1;
 // 左側已排序數組
 const left = arr.slice(start, mid + 1);
 // 右側已排序數組
 const right = arr.slice(mid + 1, end + 1);
 // 加入守衛元素,這樣能夠不用判斷子數組是否爲空
 left.push(Infinity);
 right.push(Infinity);
 // 依次取出兩個子數組中的較小的值
 let i = 0;
 let l = 0;
 let r = 0;
 while(i < count) {
 if (left[l] < right[r]) {
 arr[start + i] = left[l];
 l++;
 } else {
 arr[start + i] = right[r];
 r++;
 }
 i++;
 }
}

能夠把兩個已排序的子數組看做是兩堆撲克,每次從兩隊撲克中取出較小的一張牌,直到全部的牌取完,獲得的就是一副排好序的撲克。blog

下面看一下如何使用遞歸實現歸併排序:
image.png
首先計算出中心點將數組分割成兩個子數組,對兩個子數組分別排序,最後調用merge函數將兩個已排序的子數組合並獲得最終的排序數組。排序

相關文章
相關標籤/搜索