【算法知识】详解归并排序算法
已發(fā)布:
【算法知識】詳解選擇冒泡算法
【算法知識】詳解選擇排序算法
【算法知識】詳解插入排序算法
【算法知識】詳解快速排序算法
基本思想
歸并排序的基本思想是:
先將序列一次次分成子序列,直到子序列長度為1;
再將已有序的子序列合并,得到完全有序的序列。
可以看出歸并排序運用了 分而治之的思想 。
例子
輸入數(shù)組 [ 2, 5, 3 , 10, ?-3, ?1 , 6 , 4];
初始狀態(tài)如下:
分治思想如下:
首先把數(shù)組依次折半,分成小的子數(shù)組,直到每一個子數(shù)組的長度都為1;
然后合并子數(shù)組,在合并的過程中進(jìn)行排序;
如下圖:
將數(shù)組分成子數(shù)組的方法比較簡單,不過多介紹;
下面介紹一下合并操作,以最后一次合并為例:
下圖是最后一次合并前的兩個數(shù)組:
定義兩個變量 left和right,分別賦值為兩個數(shù)組的首元素的索引;
初始化一個數(shù)組,數(shù)組長度為原數(shù)組大小;
再定義一個變量,t,初始化為新開的數(shù)組的第一個元素的索引,即0;
如下圖:
然后每次從兩個數(shù)組中找相對較小的數(shù),填到新開的數(shù)組中;
-3 < 2,將-3填到數(shù)組中,right++;
狀態(tài)2t++;
狀態(tài)31< 2,將1填到數(shù)組中,right++;
狀態(tài)4t++;
狀態(tài)52 < 4,將2填到數(shù)組中,left++;
狀態(tài)6t++
狀態(tài)73 < 4,將3填到數(shù)組中,left++;
狀態(tài)8t++
狀態(tài)94 < 5,將4填到數(shù)組中,right++;
狀態(tài)10t++
狀態(tài)115 < 6,將5填到數(shù)組中,left++;
狀態(tài)12t++
狀態(tài)136 < 10,將6填到數(shù)組中,right++后越界
狀態(tài)14t++
狀態(tài)15再把剩余的數(shù)加到數(shù)組里,直到子數(shù)組中的數(shù)都填過來;
狀態(tài)16動圖如下:
動態(tài)圖代碼
注意:
代碼中的right和例子中的right含義不同;
具體含義見代碼參數(shù)注釋。
先來看合并子數(shù)組的代碼;
函數(shù)聲明如下:
然后是合并的方法
public?static?void?merge(int[]?arr,?int?left,?int?mid,?int?right,?int[]?temp)?{//左邊有序序列的初始索引int?i?=?left;?//右邊有序序列的初始索引int?j?=?mid?+?1;?int?t?=?0;?//?指向臨時數(shù)組的當(dāng)前索引//將兩邊數(shù)組的元素進(jìn)行比較,依次填進(jìn)臨時數(shù)組//直到將一邊填完while?(i?<=?mid?&&?j?<=?right)?{//選擇較小的添加進(jìn)去if(arr[i]?<=?arr[j])?{temp[t]?=?arr[i];t?+=?1;i?+=?1;}?else?{?temp[t]?=?arr[j];t?+=?1;j?+=?1;}}//把有剩余數(shù)據(jù)的數(shù)組全部填充到數(shù)組//肉眼可以判別哪個有數(shù)據(jù),但是計算機需要用循環(huán)條件判別//所以有兩個while循環(huán)while(?i?<=?mid)?{temp[t]?=?arr[i];t?+=?1;i?+=?1;}while(?j?<=?right)?{?temp[t]?=?arr[j];t?+=?1;j?+=?1;}//將temp數(shù)組的元素拷貝到arrt?=?0;int?Left?=?left;?while(Left?<=?right)?{arr[Left]?=?temp[t];t?+=?1;Left?+=?1;}}歸并代碼:
?//歸并(分+治)方法public?static?void?mergeSort(int[]?arr,?int?left,?int?right,?int[]?temp)?{if(left?<?right)?{int?mid?=?(left?+?right)?/?2;?//中間索引//左邊遞歸分解mergeSort(arr,?left,?mid,?temp);//右邊遞歸分解mergeSort(arr,?mid?+?1,?right,?temp);//合并merge(arr,?left,?mid,?right,?temp);}}全代碼
import?java.util.Arrays;public?class?Solution?{public?static?void?main(String[]?args)?{int?[]arr=?new?int[]{2,5,3,10,-3,1,6,4};int?[]temp?=?new?int[arr.length];mergeSort(arr,0,arr.length-1,temp);System.out.println(Arrays.toString(arr));}//歸并(分+治)方法public?static?void?mergeSort(int[]?arr,?int?left,?int?right,?int[]?temp)?{if(left?<?right)?{int?mid?=?(left?+?right)?/?2;?//中間索引//左邊遞歸分解mergeSort(arr,?left,?mid,?temp);//右邊遞歸分解mergeSort(arr,?mid?+?1,?right,?temp);//合并merge(arr,?left,?mid,?right,?temp);}}//合并的方法/****?@param?arr?排序的原始數(shù)組*?@param?left?左邊有序序列的初始索引*?@param?mid?中間索引*?@param?right?右邊索引*?@param?temp?做中轉(zhuǎn)的數(shù)組*/public?static?void?merge(int[]?arr,?int?left,?int?mid,?int?right,?int[]?temp)?{//左邊有序序列的初始索引int?i?=?left;//右邊有序序列的初始索引int?j?=?mid?+?1;int?t?=?0;?//?指向臨時數(shù)組的當(dāng)前索引//將兩邊數(shù)組的元素進(jìn)行比較,依次填進(jìn)臨時數(shù)組//直到將一邊填完while?(i?<=?mid?&&?j?<=?right)?{//選擇較小的添加進(jìn)去if(arr[i]?<=?arr[j])?{temp[t]?=?arr[i];t?+=?1;i?+=?1;}?else?{temp[t]?=?arr[j];t?+=?1;j?+=?1;}}//把有剩余數(shù)據(jù)的數(shù)組全部填充到數(shù)組//肉眼可以判別哪個有數(shù)據(jù),但是計算機需要用循環(huán)條件判別//所以有兩個while循環(huán)while(?i?<=?mid)?{temp[t]?=?arr[i];t?+=?1;i?+=?1;}while(?j?<=?right)?{temp[t]?=?arr[j];t?+=?1;j?+=?1;}//將temp數(shù)組的元素拷貝到arrt?=?0;int?Left?=?left;while(Left?<=?right)?{arr[Left]?=?temp[t];t?+=?1;Left?+=?1;}} }時間復(fù)雜度
歸并排序的是按照分層進(jìn)行比較的,會分成層;
而每一層的比較次數(shù)為;
所以時間復(fù)雜度求得。
穩(wěn)定性
在交換元素時,可以限定元素相等時不移動,所以歸并排序是可以穩(wěn)定的。
往期精彩回顧適合初學(xué)者入門人工智能的路線及資料下載機器學(xué)習(xí)在線手冊深度學(xué)習(xí)在線手冊AI基礎(chǔ)下載(pdf更新到25集)本站qq群1003271085,加入微信群請回復(fù)“加群”獲取一折本站知識星球優(yōu)惠券,復(fù)制鏈接直接打開:https://t.zsxq.com/yFQV7am喜歡文章,點個在看
總結(jié)
以上是生活随笔為你收集整理的【算法知识】详解归并排序算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大神接棒,YOLOv4来了!
- 下一篇: 【面试招聘】非科班的秋招攻略贴