1. 程式人生 > 實用技巧 >資料結構012_排序演算法(歸併排序)

資料結構012_排序演算法(歸併排序)

其實我到希爾排序就有點不懂了。就反反覆覆碼很多遍。最後搞得能敲出來但是清楚知道還是不懂。

但是我有良好的自信系統,我知道我不屬於笨蛋,如果不懂,那就是確實需要多付出一些精力。

我期待我像小學生背乘法口訣,不知所云,但突然有一天茅塞頓開,啊原來是這麼用的。

本篇內容:歸併排序

圖例:

程式碼:

package com.njcx.test5;

import java.util.Arrays;

public class SortAlgorithm {

    /**
     * 歸併排序(Merge-sort)是利用歸併的思想實現的排序方法,該方法採用經典的分治(divide-and-conquer)策略,
     * 
     * 歸併排序的示例圖很像完全二叉樹,可以使用遞迴實現歸併排序,也可以使用迭代實現。 分的階段可以理解成遞迴拆分子序列的過程。
     * 治的階段需要將兩個已經有序的子序列合併成一個有序序列。
     
*/ public static void main(String[] args) { int[] arr = { 8, 4, 5, 3, 1, 7, 6, 2 }; System.out.println("原始陣列:" + Arrays.toString(arr)); int[] temp = new int[arr.length];// 歸併排序是需要一個額外的空間開銷的 mergeSort(arr, 0, arr.length - 1, temp); System.out.println("歸併排序後的陣列:" + Arrays.toString(arr)); }
/** * 分+合方法 【也不好理解】 */ public static void mergeSort(int[] arr, int left, int right, int[] temp) { if (left < right) { int mid = (left + right) / 2;// 中間索引 // 向左遞迴進行分解 mergeSort(arr, left, mid, temp); // 向右遞迴分解 mergeSort(arr, mid + 1, right, temp);
// 每分解一次就合併一次 merge(arr, left, mid, right, temp); } } /** * 合併的方法 * * @param arr * 排序的原始陣列 * @param left * 左邊有序序列的初始索引 * @param mid * 中間索引 * @param right * 右邊索引 * @param temp * 做中轉的陣列 */ public static void merge(int[] arr, int left, int mid, int right, int[] temp) { int i = left;// 初始化i,表示左邊有序序列的初始索引 int j = mid + 1;// 初始化j,表示右邊有序序列的初始索引 int t = 0;// 指向temp陣列的當前索引 // (一) 先把左右兩邊的資料按照規則填充到temp中 直到左右兩邊有序序列有一邊處理完畢為止 while (i <= mid && j <= right) { // 如果左邊有序序列的當前元素,小於右邊有序序列的當前元素 // 就將左邊的當前元素拷貝到temp陣列 if (arr[i] <= arr[j]) { temp[t] = arr[i]; t += 1; i += 1; } else if (arr[j] < arr[i]) { temp[t] = arr[j]; t += 1; j += 1; } } // (二) 把有剩餘資料的一邊,所有資料依次全部填充到temp while (i <= mid) {// 說明座標的有序序列還有剩餘的元素 temp[t] = arr[i]; t += 1; i += 1; } while (j <= right) { temp[t] = arr[j]; t += 1; j += 1; } // (三) 將temp陣列的元素拷貝到arr 【難點,你品,你細品】【不懂】 // 注意:這裡並不是每一次都8個全部拷貝 t = 0; int tempLeft = left; System.out.println("tempLeft=" + tempLeft + ",right=" + right); //方便理解加的一個輸出過程 while (tempLeft <= right) { // 第一次合併時,tempLeft=0,right=1 // 第二次tempLeft=2,right=3 // 第三次tempLeft=0,right=3 // 最後一次tempLeft=0,right=7 arr[tempLeft] = temp[t]; t += 1; tempLeft += 1; } } }

執行結果:

原始陣列:[8, 4, 5, 3, 1, 7, 6, 2]
tempLeft=0,right=1
tempLeft=2,right=3
tempLeft=0,right=3
tempLeft=4,right=5
tempLeft=6,right=7
tempLeft=4,right=7
tempLeft=0,right=7
歸併排序後的陣列:[1, 2, 3, 4, 5, 6, 7, 8]