js算法-歸併排序(merge_sort)

歸併排序(MERGE-SORT)是創建在歸併操做上的一種有效的排序算法,該算法是採用分治法(Divide andConquer)的一個很是典型的應用。將已有序的子序列合併,獲得徹底有序的序列;即先使每一個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱爲二路歸併。

歸併排序

歸併排序是一種很是穩定的排序方法,它的時間複雜度不管是平均,最好,最壞都是NlogN。算法

歸併排序的2個步驟

  1. 先拆分,一直拆分到只有一個數
  2. 拆分完成後,開始遞歸合併

拆分過程

圖片描述

從上圖能夠看出,歸併排序會將一個數組進行兩兩拆分,一直拆分到只有一個數的時候中止拆分。
那麼拆分的代碼就很簡單了,就是獲得一個指向中間的指針q,將數組拆分紅(start,p)和(p,end)兩個部分。segmentfault

  • p表示數組的開始下標
  • r表示數組的結束下標
function divide(p, r){
        return Math.floor( (p + r) / 2 );
    }

合併過程

圖片描述

合併的過程就如上圖所示數組

  1. 遍歷兩組數據
  2. 進行對比大小
  3. 較小的那個值取出來放在第一個位置

舉個例子:數據結構

  • 假設如今數組A的數據是[2,5,1,3]
  • 通過咱們的拆分後會是(0,2),(2,4);
  • 咱們經過A.slice(0,2)和A.slice(2,4)=>獲得兩個數組A1[2,5]和A2[1,3]
  • 而後咱們對數組[2,5,1,3]進行遍歷,第一次會獲得兩邊較小的數1,第二次2,第三次3,第四次是5
function merge(A, p, q, r){
        const A1 = A.slice(p, q);
        const A2 = A.slice(q, r);
        
        // 哨兵,往A1和A2裏push一個最大值,好比防止A1裏的數都比較小,致使第三次遍歷某個數組裏沒有值
        
        A1.push(Number.MAX_SAFE_INTEGER);
        A2.push(Number.MAX_SAFE_INTEGER);
        // 循環作比較,每次取出較小的那個值
        for (let i = p, j = 0, k = 0; i < r; i++) {
            if (A1[j] < A2[k]) {
              A[i] = A1[j];
              j++;
            } else {
              A[i] = A2[k];
              k++;
            }
         }
    }

主程序

主程序就是作遞歸重複上面的操做了ide

function merge_sort(A, p = 0, r) {
      r = r || A.length;
      if (r - p === 1) {
        return;
      }
      const q = divide(p, r);
      merge_sort(A, p, q);
      merge_sort(A, q, r);
      merge(A, p, q, r);
    
      return A;
    }

完整代碼

function divide(p, r) {
      return Math.floor((p + r) / 2);
    }
    
    function merge(A, p, q, r) {
      const A1 = A.slice(p, q);
      const A2 = A.slice(q, r);
      A1.push(Number.MAX_SAFE_INTEGER);
      A2.push(Number.MAX_SAFE_INTEGER);
    
      for (let i = p, j = 0, k = 0; i < r; i++) {
        if (A1[j] < A2[k]) {
          A[i] = A1[j];
          j++;
        } else {
          A[i] = A2[k];
          k++;
        }
      }
    }
    
    function merge_sort(A, p = 0, r) {
      r = r || A.length;
      if (r - p === 1) {
        return;
      }
      const q = divide(p, r);
      merge_sort(A, p, q);
      merge_sort(A, q, r);
      merge(A, p, q, r);
    
      return A;
    }

推薦閱讀

數據結構系列:
js數據結構-棧
js數據結構-鏈表
js數據結構-隊列
js數據結構-二叉樹(二叉堆)
js數據結構-二叉樹(二叉搜索樹)
js數據結構-散列表(哈希表)spa

相關文章
相關標籤/搜索