Java演算法-歸併排序

來源:互聯網
上載者:User

標籤:

  歸併排序採用的是遞迴來實現,屬於“分而治之”,將目標數組從中間一分為二,之後分別對這兩個數組進行排序,排序完畢之後再將排好序的兩個數組“歸併”到一起,歸併排序最重要的也就是這個“歸併”的過程,歸併的過程中需要額外的跟需要歸併的兩個數組長度一致的空間,比如需要規定的數組分別為: [3, 6, 8, 11] 和 [1, 3, 12, 15] (雖然邏輯上被劃為為兩個數組,但實際上這些元素還是位於原來數組中的,只是通過一些 index 將其劃分成兩個數組,原數組為 [3, 6, 8, 11, 1, 3, 12, 15 ,我們設定三個指標 lo, mid, high 分別為 0,3,7 就可以實現邏輯上的子數組劃分)那麼需要的額外數組的長度為 4 + 4 = 8 。

 

  歸併的過程可以簡要地概括為如下:

1) 將兩個子數組中的元素複製到新數組 copiedArray 中,以前面提到的例子為例,則 copiedArray = [3, 6, 8, 11, 1, 3, 12, 15] ;

2) 設定兩個指標分別指向原子數組中對應的第一個元素,假定這兩個指標取名為 leftIdx 和 rightIdx ,則 leftIdx = 0 (對應 copiedArray 中的第一個元素 [3] ), rightIdx = 4 (對應 copiedArray 中的第五個元素 [1] );

3) 比較 leftIdx 和 rightIdx 指向的數組元素值,選取其中較小的一個並將其值賦給原數組中對應的位置 i ,賦值完畢後分別對參與賦值的這兩個索引做自增 1 操作,如果 leftIdx 或 rigthIdx 值已經達到對應數組的末尾,則餘下只需要將剩下數組的元素按順序 copy 到餘下的位置即可。

 

  下面給個歸併的具體執行個體:

第一趟:輔助數組 [21 , 28, 39 | 35, 38] (數組被拆分為左右兩個子數組,以 | 分隔開)[21 ,  ,  ,  ,  ] (第一次 21 與 35 比較 , 左邊子數組勝出, leftIdx = 0 , i = 0 )第二趟:輔助數組 [21, 28 , 39 | 35, 38][21 , 28,  ,  ,  ] (第二次 28 與 35 比較,左邊子數組勝出, leftIdx = 1 , i = 1 )第三趟: [21, 28, 39 | 35 , 38] [21 , 28 , 35,  ,  ] (第三次 39 與 35 比較,右邊子數組勝出, rightIdx = 0 , i = 2 )第四趟: [21, 28, 39 | 35, 38 ] [21 , 28 , 35 , 38,  ] (第四次 39 與 38 比較,右邊子數組勝出, rightIdx = 1 , i = 3 )第五趟: [21, 28, 39 | 35, 38] [21 , 28 , 35 , 38 , 39] (第五次時右邊子數組已複製完,無需比較 leftIdx = 2 , i = 4 )

 

  以上便是一次歸併的過程,我們可以將整個需要排序的數組做有限次拆分(每次一分為二)直到分為長度為1 的小數組為止,長度為 1 時數組已經不用排序了。在這之後再逆序(由於採用遞迴)依次對這些數組進行歸併操作,直到最後一次歸併長度為 n / 2 的子數組,歸併完成之後數組排序也完成。

歸併排序需要的額外空間是所有排序中最多的,每次歸併需要與參與歸併的兩個數組長度之和相同個元素(為了提供輔助數組)。則可以推斷歸併排序的空間複雜度為 1 + 2 + 4 + … + n = n * ( n + 2) / 4 (忽略了 n 的奇偶性的判斷),時間複雜度比較難估,這裡小弟也忘記是多少了(囧)。

 

  歸併排序是建立在歸併操作上的一種有效排序演算法,歸併是指將兩個已經排序的序列合并成一個序列的操作

實現代碼:

/**   * 歸併排序<br/>   * <ul>   * <li>申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合并後的序列</li>   * <li>設定兩個指標,最初位置分別為兩個已經排序序列的起始位置</li>   * <li>比較兩個指標所指向的元素,選擇相對小的元素放入到合并空間,並移動指標到下一位置</li>   * <li>重複步驟3直到某一指標達到序列尾</li>   * <li>將另一序列剩下的所有元素直接複製到定序序列尾</li>   * </ul>   *    * @param numbers   */  public static void mergeSort(int[] numbers, int left, int right) {       int t = 1;// 每組元素個數       int size = right - left + 1;       while (t < size) {           int s = t;// 本次迴圈每組元素個數           t = 2 * s;           int i = left;           while (i + (t - 1) < size) {               merge(numbers, i, i + (s - 1), i + (t - 1));               i += t;           }           if (i + (s - 1) < right)               merge(numbers, i, i + (s - 1), right);       }   }   /**   * 歸併演算法實現   *    * @param data   * @param p   * @param q   * @param r   */  private static void merge(int[] data, int p, int q, int r) {       int[] B = new int[data.length];       int s = p;       int t = q + 1;       int k = p;       while (s <= q && t <= r) {           if (data[s] <= data[t]) {               B[k] = data[s];               s++;           } else {               B[k] = data[t];               t++;           }           k++;       }       if (s == q + 1)           B[k++] = data[t++];       else          B[k++] = data[s++];       for (int i = p; i <= r; i++)           data[i] = B[i];   }  

 

Java演算法-歸併排序

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.