此部落格為**部落格
/*歸併排序
* 思想: divide and conquer (分治法)
* 將乙個陣列等分成兩個更小的陣列,將這兩個陣列排序後,再將它們歸併起來將得到乙個有序陣列
* 具體歸併方法就是從兩個陣列中從小到大放入大陣列中
* 時間複雜度: 對於長度為n的任意陣列,自頂向下的歸併排序需要1/2n㏒n至n㏒n o(nlogn)
* 空間複雜度:需要額外為n的空間 o(n)
* 特點:執行時間比插入排序等比較大大減少,但輔助陣列所使用的額外空間和n的大小成正比
* */
package paixu;
//自頂向下的歸併排序
public class merge extends example
public static void sort(comparable a,int lo,int hi)
public static void merge(comparable a,int lo,int mid,int hi)
for(int k=lo; k<=hi; k++)
} public static void main(string args)
}/*歸併排序的改進:
* 1.對小規模陣列使用插入排序
* 2.測試陣列是否有序:可以加乙個判斷條件,如果a[mid]小於a[mid+1],我們就認為陣列已經有序並跳過merge方法
* 3.不要每次都將元素複製到輔助陣列,一次排序將輸入陣列排序到輔助陣列,一次將輔助陣列排序到輸入陣列*/
執行結果如下所示:
可以看到,將10個大小為十萬的陣列排序時,歸併排序比希爾排序要快,更不用說選擇排序、插入排序了。但歸併排序的乙個不足是需要o(n)的額外空間。
下面**我僅僅實現了改進1和2
而且僅僅修改了上述public static void sort(comparable a,int lo,int hi)函式
public static void sort(comparable a,int lo,int hi)else
} a[j+1] = tmp;
} return;
} int mid = lo + (hi-lo)/2;
sort(a,lo,mid); //將左半邊排序
sort(a, mid+1, hi); //將右半邊排序
if(less(a[mid],a[mid+1])) return; //如果a[mid]小於a[mid+1],我們就認為陣列已經有序並跳過merge方法
merge(a,lo,mid,hi); //歸併結果
}
再次執行:
說明這兩個改進作用還是挺大的。
/*自底向上的遞迴排序
* 思想:任何一種分治法演算法,都有自頂向下(遞迴)和自底向上(迴圈、迭代)的兩種實現方法。
* 下面**是先歸併最小的陣列,然後歸併得到的子陣列,如此這般,直到將整個陣列歸併在一起
* */
package paixu;
public class mergebu extends example
} public static void main(string args) ;
mergebu.sort(a);
mergebu.show(a);*/
string alg1 = "merge";
string alg2 = "mergebu";
int n = 100000;
int t = 10;
long t1 = sortcompare.timerandominput(alg1, n, t);
long t2 = sortcompare.timerandominput(alg2, n, t);}}
執行結果如下:
兩種方法執行時間基本相同。
排序演算法 5 歸併排序
歸併排序演算法思路 先將陣列不斷均分成兩堆,直至只有乙個元素,再兩兩進行排序合併。使用了大量了額外陣列空間,但減少了比較次數和寫操作。時間複雜度與空間複雜度將再排序演算法總結裡面討論。下面直接展示演算法 def merge sort nums nums為list型別 分解陣列直至陣列長度小於1 wh...
經典排序演算法 5 歸併排序
歸併排序採用分治的方法,將陣列對半地拆分成子陣列,最後再有序地合併子陣列 merge 雙指標法,比較指標元素的大小來有序合併 時間複雜度分析 設陣列長為n,將陣列分成小陣列一共要logn步,每步都是乙個合併有序陣列的過程,時間複雜度記為o n 故一共為o nlogn 歸併排序的效能不受初始資料的影響...
排序 5 歸併排序
將包含n個元素的初始序列,看成n個有序的子串行,每個序列的長度為1,然後兩兩歸併.直到得到長度為n的有序序列。遞迴和非遞迴兩種方法 5.歸併排序 遞迴 recursion 融合 void merging int list1,int list1 size,int list2,int list2 siz...