在一些經常使用的排序中,歸併排序在時間開銷上來講能夠是排序中的最佳實踐之一(時間複雜度=n*log n),今天咱們就來看看歸併是如何實現的。數組
歸併排序大體能夠分爲兩步:函數
一、將數組從中間分開,對兩邊分別排序。測試
二、將兩個有序的數組進行合併。spa
因此實現歸併排序主要也就是解決這兩個問題。code
下圖是歸併排序的大體步驟,紅線表明將數組拆開,藍箭頭表明將拆後的數組分別處理,紅箭頭表明將數組排序後返回blog
問題1:如何將數組分開,並進行分別排序?排序
答:使用遞歸實現遞歸
問題2:如何將兩個有序的數組進行合併排序?get
假設如上圖的第二行中,須要合併(2,4,5,8)和(1,3,6,7)兩個數組。
博客
1,由於這兩個數組都是增序的,只須要比較倆個數組的第一個數,那麼比較小的數必然是兩數組中最小的數。
例:比較(2,4,5,8)的2 和(1,3,6,7)的1,那麼1必然是兩數組中最小的數。
2,將這個數放入一個新的數組。
例:將1放入數組a[]中,兩數組還有(2,4,5,8)的2 和(3,6,7)
3,再次重複第1步。
.....
如此比較直到其中一個數組結束,將另外一個數組剩下的值所有放入數組a
那麼數組a即是排好序的數組。
代碼實現:
public class MergesSort { //排序函數,target爲要排序的數組, // begin和end爲要排序的區間的開始和結束座標 public void mergeSort(int target[],int begin,int end){ //當要排序的數組區間只有一個數時直接返回 if((end-begin)==0){ return ; } //當排序的數組區間有兩個數時,對這兩個數進行比較 if((end-begin==1)){ sortS2B(target,begin,end); return ; } //當要排序的數組大於2個時,咱們就分割此數組的區間,分別排序; int mid=(begin+end)/2; mergeSort(target,begin,mid); mergeSort(target,mid+1,end); //將排序好的倆數組的區間進行合併排序 //建立一個數組用於存放排好序的數組,大小就是區間大小 int temp[]=new int[end-begin+1]; //存放第一個數組的開始座標 int p1=begin; //存放第二個數組的開始座標 int p2=mid+1; //存放temp數組最近一次存放的數的座標,初始爲0 int p3=0;
while(p1<=mid&&p2<=end){ //將小的數存到temp數組 if(target[p1]<target[p2]){ temp[p3]=target[p1]; p3++; p1++; }else{ temp[p3]=target[p2]; p3++; p2++; } } //檢查是否還有沒有插入的 while(p1<=mid){ temp[p3]=target[p1]; p3++; p1++; } while(p2<=end){ temp[p3]=target[p2]; p3++; p2++; } //將排好的數組temp與原target的替換 System.arraycopy(temp, 0, target, begin, temp.length); }
//將數組target的a和b座標的兩個數按small to big從小到大排序 public void sortS2B(int target[],int begin,int end){ //若是begin>end,進行交換 if(target[begin]>target[end]){ int temp=target[begin]; target[begin]=target[end]; target[end]=temp; } return ; } public static void main(String[] args) { MergesSort ms=new MergesSort(); int a[]={8,-6,2,-7,9,-23,2,7,4,67,1,8}; //注意第三個參數是數組的結束座標,應該由於數組是從0開始的,因此結束的座標須要數組的長度-1 ms.mergeSort(a,0,a.length-1); int i=0; while(i<a.length){ System.out.print(a[i++]+" "); } } }
代碼測試:
//測試代碼 public static void main(String[] args) { MergesSort ms=new MergesSort(); int a[]={8,-6,2,-7,9,-23,2,7,4,67,1,8}; //注意第三個參數是數組的結束座標,由於數組是從0開始的,因此結束的座標須要數組的長度-1 ms.mergeSort(a,0,a.length-1); int i=0; while(i<a.length){ System.out.print(a[i++]+" "); } }
結果:
寫此博客但願之後忘記的時候可以回顧一下,代碼若是有不對的地方,請大佬們指正,謝謝~