排序演算法 3 歸併排序

2021-08-07 07:36:52 字數 4774 閱讀 8977

這篇博文分為四個部分:

歸併排序基本思想

基礎**實現與解析

**一次優化

**二次優化(自底向上的歸併排序)

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...