已知一個數組 1五、5八、6一、7五、21、32、89、4、78、83。採用遞歸實現的歸併排序將數組有序。java
分治策略:(摘自《算法導論》)算法
在分治策略中,咱們採用遞歸解決問題數組
分解:將原問題分解爲子問題,子問題與原問題同樣,只不過規模更小。ui
解決:遞歸的求解子問題,若是子問題足夠小,則中止遞歸,直接解決子問題。this
合併:將子問題的解組合爲原問題的解。spa
歸併的算法思想:blog
將倆個已經有序的數組A,B合併爲一個有序的數組C。排序
數組A:23,47,81,95 數組B:7,14,39,55,62,74遞歸
A[0]>B[0] ? C[0]=B[0] : C[0]=A[0]; 內存
以上即是歸併的主要思想。
而歸併排序就是以這種思想爲主加之遞歸的思想組成。即將已知的一個數組拆分爲兩個子數組,
在分別將倆個子數組再次分別拆分爲倆個子數組,直到沒法拆分爲止,即子數組只有一個數組元素,而後對每一個子數組排序,使之成爲有序子數組,而後將子數組合並。最後造成一個排序好的完整數組。
遞歸-歸併排序的缺點
1:歸併排序須要一個和原數組大小相等的數組輔助,進行數據的排序。消耗額外的內存。
2:遞歸是一種很好的解決問題的思路,可是遞歸因爲須要保存「相關參數以及引用地址」,因此遞歸會有額外的內存開銷。
因此綜上,當數據量很是大的時候使用遞歸-歸併排序就須要考慮「空間問題」。
歸併排序是一個運行時間爲NlgN的算法
如下是java實現遞歸-歸併排序
public class GuiBingOrder {
private int[] Array;
private int currentIndex;
private int maxIndex;
public GuiBingOrder(int size) {
this.Array = new int[size];
this.currentIndex = 0;
this.maxIndex = size-1;
}
public void insert(int value) {
if(this.maxIndex<this.currentIndex) {
System.out.println("數組已滿");
}else {
this.Array[this.currentIndex++] = value;
}
}
public void doOrder() {//開始排序
int[] orderArray = new int[this.currentIndex]; //須要額外開銷的數組
this.GuiBinOrder(orderArray,0,this.currentIndex-1);
}
private void GuiBinOrder(int[] orderArray,int begin,int end) {
if(end==begin) { //當數組不可拆分時,即只有一個元素時。
return;
}
int middle = (begin+end)/2;
this.GuiBinOrder(orderArray,begin, middle); //遞歸的思想:對左半邊數組進行拆分。
this.GuiBinOrder(orderArray,middle+1, end); //遞歸的思想:對右半邊數組進行拆分。
this.order(orderArray,begin,middle+1,end);//歸併的思想:對子數組進行排序合併。
}
private void order(int[] orderArray,int begin,int middle,int end) {
int i = begin;
int j = middle;//右邊子數組起始
int mid = middle-1;//左邊子數組尾
int size = end-begin+1;
int index = 0;
while(i<=mid&&j<=end) { //A[0]>B[0] ? C[0]=B[0] : C[0]=A[0]; 比較並插入數組C A數組至關於左邊子數組,B數組至關於右邊子數組。
if(this.Array[i]>this.Array[j]) {
orderArray[index++]=this.Array[j++];
}else {
orderArray[index++]=this.Array[i++];
}
};
while(i<=mid) {//當右邊子數組B爲空時,左邊子數組A依然有元素,將剩餘元素依次插入數組C
orderArray[index++] = this.Array[i++];
};
while(j<=end) {//當左邊子數組A爲空時,右邊子數組B依然有元素,將剩餘元素依次插入數組C
orderArray[index++] = this.Array[j++];
};
for(index=0;index<size;index++) { //將額外開銷數組中已排序好的元素依次從 本次遞歸起始點複製回原數組
this.Array[begin+index] = orderArray[index];
}
}
public void show() {
for (int i : Array) {
System.out.println(i);
}
}
}
排序結果爲:4、15、21、32、58、61、75、78、83、89