這篇博文分為四個部分:
歸併排序基本思想
基礎**實現與解析
**一次優化
**二次優化(自底向上的歸併排序)
1.歸併排序基本思想
* 3)* [歸併排序
] :小到大排序
* 1.
迴圈的將每乙個部分都分為原來的一半
,直到最後每一部分只剩下乙個元素
* 2.
迴圈的將每兩個部分進行合併並且排序
,直到最後全部合併
* o(n*log n)
2.基礎**實現與解析
static intmergesort(intarr)
private static int__mergesort(intarr,
intleft,
intright)
//得到中點位置的下標
middle,
注意這裡最好不要使用
int middle = (right + left) / 2 ,
防止right + left
資料太大造成溢位
intmid = (right - left) / 2 + left;
//1.
迴圈的將每乙個部分都分為原來的一半
,直到最後每一部分只剩下乙個元素
__mergesort
(arr, left,
mid);
__mergesort
(arr,
mid + 1
, right);
//2.
迴圈的將每兩個部分進行合併並且排序
,直到最後全部合併
// if
條件判斷當這兩部分需要排序時
(即前一部分的最大值要比後一部分的最小值大時
),進行排序
,否則直接合併即可
if(arr[mid] > arr[mid + 1])
returnarr;
}
private static int__mergesort(intarr,
intleft,
intright)
//得到中點位置的下標
middle,
注意這裡最好不要使用
int middle = (right + left) / 2 ,
防止right + left
資料太大造成溢位
intmid = (right - left) / 2 + left;
//1.
迴圈的將每乙個部分都分為原來的一半
,直到最後每一部分只剩下乙個元素
__mergesort
(arr, left,
mid);
__mergesort
(arr,
mid + 1
, right);
//2.
迴圈的將每兩個部分進行合併並且排序
,直到最後全部合併
// if
條件判斷當這兩部分需要排序時
(即前一部分的最大值要比後一部分的最小值大時
),進行排序
,否則直接合併即可
if(arr[mid] > arr[mid + 1])
returnarr;}//
將arr[left....mid]
與arr[mid + 1....right]
兩個部分進行歸併
private static int__merge
(intarr,
intleft,
intmid,
intright)
inti = left;
//作為前一部分將要排序的元素的下標
intj = mid + 1
;
//作為後一部分將要排序的元素的下標
for(
intk = left; k <= right; k++)else if(j > right)
//一般情況
: 遍歷整個陣列,比較
temarr[i - left]
與temarr[j - left]
的大小,
將小的直接覆蓋原陣列
arr,
將它排到前面
,並且將排完序的下標後移
else if(
temarr[i - left] < temarr[j - left])else
}returntemarr
;}
3.**一次優化
由於最初歸併排序分割到最後會只剩下乙個元素,然後這乙個元素不斷的通過遞迴的方式合併合併再合併,因此這裡可以不遞迴切分到底,而在只剩下10個元素的時候,使用插入排序對它進行排序,然後直接向上合併.
這種做法權衡了效能的消耗.
在這裡只需要修改 __mergesort(int arr,int left,int right)
這個方法:
private static int__mergesort(intarr,
intleft,
intright)
/*優化開始
*/if(right - left <= 10
) //
使用插入排序進行底層的排序
,優化歸併排序不斷遞迴到底的消耗
temparr =insertionsort.insertionsort_3
(temparr);
for(
inti = left; i <= right; i++)
returnarr;
} /*
優化結束
*///
得到中點位置的下標
middle,
注意這裡最好不要使用
int middle = (right + left) / 2 ,
防止right + left
資料太大造成溢位
intmid = (right - left) / 2 + left;
//1.
迴圈的將每乙個部分都分為原來的一半
,直到最後每一部分只剩下乙個元素
__mergesort
(arr, left,
mid);
__mergesort
(arr,
mid + 1
, right);
//2.
迴圈的將每兩個部分進行合併並且排序
,直到最後全部合併
// if
條件判斷當這兩部分需要排序時
(即前一部分的最大值要比後一部分的最小值大時
),進行排序
,否則直接合併即可
if(arr[mid] > arr[mid + 1])
returnarr;
}
4.**二次優化(自底向上的歸併排序)
注意看歸併排序的第一步:將每個大的部分都切分為原來的一半,直到最後只剩下乙個元素.
如果是從計算機本身的視角來看,他始終是同乙個陣列,因此迴圈的二分操作可以幫助我們理解原理,但是對計算機來說卻無異於徒增負擔,所以這裡就沒有必要執行切分操作.
[思路]:我們可以直接把它看做是已經切分成了多個小部分,直接歸併就好
我們直接修改 mergesort(int arr) 這個方法就好:
static intmergesort經過這一步的優化,我們甚至都不需要(intarr)else}}
returnarr;
}
__mergesort(intarr,
intleft,
intright)
這個方法,就可以實現歸併排序
排序演算法 歸併排序
歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。首先考慮下如何將將二個有序數列合併。這個非常簡單,只要從比較二個數列的第乙個數,誰小就先取誰,取了後就在對應數列中刪除這個數。然後再進行比較,如果有數列為空,那直接將另...
排序演算法 歸併排序
include include define status int define max 20 typedef struct elemtype typedef struct sqlist void inital sqlist l 初始化 bool lt int i,int j void merge ...
排序演算法 歸併排序
歸併排序的思想其實完全是分治法的思想的體現,它完全遵循分治法的模式。這裡有必要再重提下分治法的思想 將原有的問題分解為幾個規模較小的但類似於原問題的子問題,遞迴的求解這些子問題,然後再合併這些子問題的解來求得原問題的解。現在來看看歸併排序的操作 1 將等待排序的含有 n 個元素的序列分解成各具有 n...