1. 程式人生 > >歸併排序非遞迴實現Java

歸併排序非遞迴實現Java

遞迴實現的歸併排序,需要O(lgN)的棧空間,而非遞迴實現的歸併排序則不需要

原文地址:http://www.jianshu.com/p/39dd1d9b491d

public class Sort {

    public static void MergeSort2(int[] arr)
    {
        //使用非遞迴的方式來實現歸併排序
        int len = arr.length;
        int k = 1;

        while(k < len)
        {
            MergePass(arr, k, len);
            k *= 2;            
        }
    }

    //MergePass方法負責將陣列中的相鄰的有k個元素的字序列進行歸併
    private static void MergePass(int[] arr, int k, int n)
    {
        int i = 0;
        int j;

        //從前往後,將2個長度為k的子序列合併為1個
        while(i < n - 2*k + 1)
        {
            merge(arr, i, i + k-1, i + 2*k - 1);
            i += 2*k;
        }

        //這段程式碼保證了,將那些“落單的”長度不足兩兩merge的部分和前面merge起來。
        if(i < n - k )
        {
            merge(arr, i, i+k-1, n-1);
        }

    }

    //merge函式實際上是將兩個有序數組合併成一個有序陣列
    //因為陣列有序,合併很簡單,只要維護幾個指標就可以了
    private static void merge(int[] arr, int low, int mid, int high)
    {
        //temp陣列用於暫存合併的結果
        int[] temp = new int[high - low + 1];
        //左半邊的指標
        int i = low;
        //右半邊的指標
        int j = mid+1;
        //合併後陣列的指標
        int k = 0;

        //將記錄由小到大地放進temp陣列
        for(; i <= mid && j <= high; k++)
        {
            if(arr[i] < arr[j])
                temp[k] = arr[i++];
            else
                temp[k] = arr[j++];
        }

        //接下來兩個while迴圈是為了將剩餘的(比另一邊多出來的個數)放到temp陣列中
        while(i <= mid)
            temp[k++] = arr[i++];

        while(j <= high)
            temp[k++] = arr[j++];

        //將temp陣列中的元素寫入到待排陣列中
        for(int l = 0; l < temp.length; l++)
            arr[low + l] = temp[l];
    }
}