分治法算法——歸併排序

分治法算法中的經典——歸併排序

上一節,我講了分治法的相關思想,並貼出數字旋轉方陣的代碼以及解決思想。算法的話,主要還是要靠自己領悟,要多思考,不會再去看看別人的思路。以下,我分析一下分治法算法中的經典——歸併排序。

下面舉個例子:
有個int數組,元素爲{1,6,2,7,4,9}
這裏寫圖片描述
首先,我們先將整個數組分解,分解成一個個規模大小相同的子問題,直到只有一個元素(圖中第四行)。現在,我們再進行合併(圖中第五六七行)。
合併的時候,就是將兩個數組不斷進行合併。以下是我的代碼,裏面有詳細的註釋。

show you my code :

import java.util.Scanner;

/**
 * 歸併排序
 * 
 * @author chenjuxnu
 * @since 2016-1-20
 * 
 */
public class Main {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        /** 輸入數組的長度 */
        int num = scan.nextInt();
        /** 用於存放數據的數組 */
        int arr[] = new int[num];
        /** 用於合併數據的數組 */
        int result[] = new int[num];
        /** 將控制檯的內容輸入至數組內 */
        for (int i = 0; i < num; i++) {
            arr[i] = scan.nextInt();
        }
        scan.close();
        /** 調用歸併方法 */
        MergeSort(0, num - 1, arr, result);
        /** 輸出內容 */
        for (int i = 0; i < num; i++) {
            System.out.print(result[i] + " ");
        }
    }

    /**
     * 歸併排序的遞歸方法
     * 
     * @param start
     *            數組的開始值
     * @param end
     *            數組的結束值
     * @param arr
     *            存放用戶輸入數據的數組
     * @param result
     *            用於存放合併後的數組
     */
    public static void MergeSort(int start, int end, int arr[], int result[]) {
        /** 用於保存中間值 */
        int m;
        // 如果開始下標等於結束下標,則結束遞歸
        if (start == end) {
            return;
        } else {
            m = (start + end) / 2;
            // 遞歸調用左部分數據
            MergeSort(start, m, arr, result);
            // 遞歸調用右部分數據
            MergeSort(m + 1, end, arr, result);
            // 合併數組
            Merge(arr, start, m, end, result);
            // 將排序好的子序列放會到arr數組裏
            for (int i = start; i <= end; i++) {
                arr[i] = result[i];
            }
        }
    }

    /**
     * 用於合併數組的內容,並放到result數組內
     * 
     * @param arr
     *            需要合併的數組
     * @param start
     *            需要合併的數組的開始下標
     * @param mid
     *            需要合併的數組的(開始下標+結束下標)/2
     * @param end
     *            需要合併的數組的結束下標
     * @param result
     *            用於存放合併後的數組
     */
    public static void Merge(int arr[], int start, int mid, int end,
            int result[]) {
        /** 用於記錄需要合併的第二個數組的下標 */
        int j = mid + 1;
        /** 用於記錄result數組的下標 */
        int num = start;
        // 如果需要合併的第一個數組跟第二個數組均有數值可以比較
        while (start <= mid && j <= end) {
            if (arr[start] < arr[j]) {
                result[num++] = arr[start++];
            } else {
                result[num++] = arr[j++];
            }
        }
        // 如果需要合併的第二個數組沒數值了,就將第一個數組依次放入result數組內
        while (start <= mid) {
            result[num++] = arr[start++];
        }
        // 如果需要合併的第一個數組沒數值了,就將第二個數組依次放入result數組內
        while (j <= end) {
            result[num++] = arr[j++];
        }

    }

}
發佈了43 篇原創文章 · 獲贊 68 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章