1. 程式人生 > 實用技巧 >排序演算法——歸併排序

排序演算法——歸併排序

  • 排序邏輯

    將一個佇列遞迴均分為兩個陣列,再將兩個陣列按序歸併為一個數組

    • 初始佇列

    • 均分為兩個佇列

    • 按序歸併

  • 程式碼示例(遞迴實現)

    /**
    * 歸併排序:
    * 將一個數組遞迴均分為兩個陣列,再將兩個陣列歸併為一個數組
    * @param arr
    * @param start 陣列範圍
    * @param end
    */
    public static void mergeSort(int[] arr, int start, int end){
        int middle = (start + end) / 2;
        if(start<end){
            //分為兩個陣列
            mergeSort(arr,start,middle);
            mergeSort(arr,middle+1, end);
            //合併
            merge(arr,start,middle,end);
        }
    }
    
    /**
    * 兩個陣列歸併為一個數組
    * @param arr
    * @param start     兩個陣列的範圍
    * @param middle
    * @param end
    */
    private static void merge(int[] arr, int start, int middle, int end) {
        //臨時陣列用來儲存歸併後的資料
        int[] temp = new int[end-start+1];
        //第一個陣列的索引
        int i = start;
        //第二個陣列的索引
        int j = middle+1;
        //臨時陣列的索引
        int index = 0;
        //兩個陣列逐一比較,小的放進臨時陣列
        while(i<=middle&&j<=end){
            if(arr[i]<arr[j]){
                temp[index++] = arr[i++];
            }else{
                temp[index++] = arr[j++];
            }
        }
        //兩個陣列中沒有剩下的元素逐一放進臨時陣列
        while(i<=middle){
            temp[index++] = arr[i++];
        }
        while(j<=end){
            temp[index++] = arr[j++];
        }
        //將臨時陣列放進源陣列
        for(int k=0;k<temp.length;k++){
            //源陣列為arr[start,end]
            arr[k+start] = temp[k];
        }
    }
    
  • 程式碼示例(迭代實現)

    public static void mergeItSort(int[] arr, int n){
        int i,left_min,left_max,right_min,right_max;
        int[] temp = new int[n];
        //i代表步長
        for(i=1; i<n; i*=2){
            for(left_min=0; left_min<n-i; left_min=right_max){
                left_max = right_min = left_min+i;
                right_max = right_min + i;
                if(right_max > n){
                    right_max = n;
                }
                //臨時陣列的指標
                int next = 0;
                while(left_min<left_max && right_min<right_max){
                    if(arr[left_min] < arr[right_min]){
                        temp[next++] = arr[left_min++];
                    }else{
                        temp[next++] = arr[right_min++];
                    }
                }
                //將左邊剩下的部分放在右邊尾部
                while(left_min<left_max){
                    arr[--right_min] = arr[--left_max];
                }
                //將臨時陣列中的資料放入原陣列
                while(next>0){
                    arr[--right_min] = temp[--next];
                }
            }
    
    
        }
    }
    
  • 事件複雜度

    O(nlogn)