1. 程式人生 > >分治演算法的完美使用----歸併排序

分治演算法的完美使用----歸併排序

歸併排序(Merge Sort)演算法完全依照了分治模式
  分解:將 n 個元素分成各含 n/2 個元素的子序列;
  解決:對兩個子序列遞迴地排序;
  合併:合併兩個已排序地子序列以得到排序結果;
和快速排序不同的是
  歸併的劃分比較隨意,快排重點就是劃分
  歸併的重點就是合併,快排不需要合併

程式碼:

import java.util.Arrays;

public class MergeSort {

    public static void main(String[] args) {
        int arr[] = new int[10];
        
for(int i=0;i<10;i++){ arr[i] = (int) ((Math.random()+1)*10); } System.out.println("排序前:"+Arrays.toString(arr)); mergeSort(arr, 0, arr.length-1); System.out.println("排序後:"+Arrays.toString(arr)); } /** * 思路:將陣列分為左右兩個陣列,遞迴呼叫歸併進行排序 * 分別排序完成後,使用輔助的合併函式將兩個有序的子數組合併成一個整體有序的陣列 * 時間複雜度:均:O(nlgn),好:O(nlgn),壞:O(nlgn) * 空間複雜度:需要開闢輔助空間,該輔助空間可以重用,大小為N * 非原址排序 * 穩定性:所有排序都是歸併,在左的永遠在左,在右的永遠在右,穩定
*/ static int[]helper; private static void mergeSort(int[] arr, int p, int r) { if (p<r) { int mid = p + ((r-p)>>1); mergeSort(arr, p, mid); // 對左側排序 mergeSort(arr, mid+1, r); // 對右側排序 merge(arr,p,mid,r); //
合併 } } private static void merge(int[] arr, int p, int mid, int r) { // 下面這行程式碼只能在這裡使用,不能在主方法使用。 helper = Arrays.copyOf(arr, arr.length); //開闢的一個輔助空間 並拷貝資料 int left = p; // 左側隊伍的頭部指標,指向待比較的元素 int right = mid + 1; // 右側隊伍的頭部指標,指向待比較的元素 int current = p; // 原陣列的指標,指向待填入資料的位置 while(left<=mid&&right<=r){ if (helper[left]<=helper[right]) { arr[current] = helper[left]; current++; left++; }else { arr[current] = helper[right]; current++; right++; } } // 如果輔助陣列右側的資料沒有全部填入原陣列 那麼不用管 因為原陣列資料存在的 // 那麼只需要考慮輔助陣列左側的資料沒有全部填入原陣列的情況 if (left<=mid) { while(left<=mid){ arr[current] = helper[left]; current++; left++; } } } }

結果: