歸併排序算法
算法平均時間複雜度:O(nlog2n)數組
算法空間複雜度:O(n) (用於存儲有序子序列合併後有序序列)spa
原理:所謂歸併排序是指將兩個或兩個以上有序的數列(或有序表),合併成一個仍然有序的數列(或有序表)。這句話講的很是明白,有序,前提就是有序。code
步驟分析:blog
一、劃分子集排序
二、合併子集遞歸
先說一下歸併算法合併的思路,也是核心:(升序)假設有一數組,分紅兩個子數組,子數組每次分別各取出一個數字進行比較(子數組取的元素索引都從小到大),將小的放入準備好的臨時數組,當兩個字數組中有一個數組的全部元素都比較過了,那就將另外一數組剩餘的元素依次放入臨時數組中。那麼這一趟結果就是有序排列好了。前提是兩個子數組都是有序的。舉個栗子:索引
1)假設有數組 [12,5,8,14,7,6](子數組無序)class
先劃分爲兩個子數組[12,5,8],[14,7,6],並有一個臨時數組temp[]原理
12 與 14 比較, 12放入temp[]中 temp[12]
5 與 14 比較, 5 放入temp[]中 temp[12,5]
8 與 14 比較, 8 放入temp[]中 temp[12,5,8]
子數組中[12,5,8]全部元素都比較完,剩餘的另外子數組元素依次放入temp[] temp[12,5,8,14,7,6]
可見子數組無序獲得的結果並非排好序的。
2)假設有數組 [5,8,12,6,7,14](子數組有序)
先劃分爲兩個子數組[5,8,12],[6,7,14],並有一個臨時數組temp[]
5 與 6 比較, 5 放入temp[]中 temp[5]
8 與 6 比較, 6 放入temp[]中 temp[5,6]
8 與 7 比較, 7 放入temp[]中 temp[5,6,7]
8 與 14 比較, 8 放入temp[]中 temp[5,6,7,8]
12 與 14 比較, 12放入temp[]中 temp[5,6,7,8,12]
子數組中[5,8,12]全部元素都比較完,剩餘的另外子數組元素依次放入temp[] temp[5,6,7,8,12,14]
可見子數組有序獲得的結果是排序好的。
怎樣才能保證兩邊子數組是有序?當一個數組只有一個元素的時候,即算爲有序的,而後用上面的第二個例子的思路歸併,即爲排序好的。
也就是說咱們要先將要比較的數組arr[],拆分爲和數組arr.length一樣多的子數組,而後兩兩歸併,如圖1所示:
圖1 歸併排序
代碼:附註釋
1 public static void Merge(int[] arr,int low,int mid,int high){ 2 int[] temp = new int[high - low + 1];// 3 int i = low;//左邊部分起始索引
4 int j = mid + 1;//右邊部分起始索引
5 int index = 0; 6 //比較將較小的放入temp中
7 while(i <= mid && j <= high){ 8 if(arr[i]<arr[j]){ 9 temp[index++] = arr[i++]; 10 }else if(arr[i]>arr[j]){ 11 temp[index++] = arr[j++]; 12 } 13 } 14 //把左邊剩餘的全放入臨時數組中
15 while(i <= mid){ 16 temp[index++] = arr[i++]; 17 } 18 //把右邊剩餘的全放入臨時數組中
19 while(j <= high){ 20 temp[index++] = arr[j++]; 21 } 22 //最後將臨時數組覆蓋原數組
23 for (int x = 0; x < temp.length; x++) { 24 arr[x+low] = temp[x]; 25 } 26 } 27 public static void MergeSort(int[] arr,int low,int high){ 28 if(low < high){ 29 int mid = (low+high)/2; 30 //將其分爲兩部分
31 MergeSort(arr,low,mid);//左邊遞歸(再分兩部分)
32 MergeSort(arr,mid+1,high);//右邊遞歸(再分兩部分) 33 //歸併
34 Merge(arr,low,mid,high); 35 } 36 }