演算法簡結 遞迴分治(二) 合併排序

2022-04-10 00:08:46 字數 1677 閱讀 2934

1.合併排序

基本思想就是先將n含有個元素的集合分成n/2個元素的子集合,分別對兩個子集合進行合併排序,最後將排好序的子集合合併。我用一張例項圖來概括一下。

待排序集合為,首先將這個集合左右分解成兩個子集合,,直到集合中的元素為乙個(只有乙個元素當然是已排好的)。再依次將兩個已排序的子集合合併。最近在看的一部演算法書中強調軟體工程的api形式,即先api,再實現。那我也來試寫下此演算法的api。

合併排序的api

void mergesort(comparable list)

演算法的入口

void mergesort(comparable list, int low, int high)

排序從low到high的元素

void merge(comparable list, int low, int mid, int high)

在mergesort中呼叫,將子集合[low...mid]和[mid+1...high]合併

我們先宣告乙個臨時陣列來輔助儲存元素,而不在用每次合併時新宣告乙個陣列。

private static comparable tmp;

這樣核心演算法的實現就簡單了,如下

mergesort

這裡要注意下merge方法頭同樣是用private修飾的,因為只有mergesort才能呼叫它,對於類外肯定是隱藏的(物件導向的封裝屬性)。

merge

1

private

static

void merge(comparable list, int low, int mid, int

high)210

11for(int k = low; k <= high; k++)

1222 }

2.自底向上的合併排序

上面這種合併,被稱為自頂向下的合併排序。其實只要將兩個有序的集合合併成乙個更大的有序集合就是合併操作。所以我們為什麼不先合併那些微笑的集合,然後再成對合併得到的子集合。事實上這種方法比前面那種方法在**上更加簡潔。

所以我們先兩兩合併,然後再四四合併,...這樣合併到頂。如果把元素個數不是2的冪的情況考慮進來的話,在最後乙個合併中,第二個子集合一定小於或等於第乙個子集合。

我把這個方法命名為mergesortbu即為bottom-up mergesort,實現如下

mergesortbu

1

public

static

extends comparable> void

mergesortbu(e list)213

}14 }

該方法完成子陣列大小從小到大的合併,每一次進行的合併都是用迴圈劃分成幾個合併操作,即把兩個小陣列[low...low+size-1]和[low+size...low+size*2 -1](若最後乙個陣列有這麼長的話)合併。

兩種排序方法在進行比較和訪問陣列的次數和順序會有所不同,關鍵還是元素個數是不是2的冪。你是希望像mergesort()一樣化整為零的解決方式,還是希望像mergesortbu()那樣循序漸進的解決方法呢?

3.改進

還可以對合併排序進行3項改進:加快小陣列的排序速度,檢測陣列是否已經有序以及通過在遞迴中狡猾引數來避免陣列複製。

分治演算法(二)合併排序

1.問題分析 合併排序問題給定的是乙個無序的序列,可以把待排序的元素分解為兩個規模大致相等的子串行。如果還是不容易解決就繼續將子串行分解,直到子串行中的元素個數為1,因為單個元素的序列本身是有序的,此時便可以進行合併,從而得到乙個完整的有序序列。2.演算法設計 1 分解 將待排序元素分成大小大致相同...

分治演算法之合併排序

合併排序法是將兩個 或兩個以上 有序表合併成乙個新的有序表,即把待排序序列分為若干個子串行,每個子串行是有序的。然後再把有序子串行合併為整體有序序列 1 分解 將待排序元素分成大小大致相同的兩個子串行 2 治理 對兩個子串行進行合併排序 3 合併 將排好序的有序子串行進行合併,得到最終的有序序列 合...

分治 合併排序 自然合併排序(C )

演算法步驟 引用自 菜鳥教程 申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合併後的序列 設定兩個指標,最初位置分別為兩個已經排序序列的起始位置 比較兩個指標所指向的元素,選擇相對小的元素放入到合併空間,並移動指標到下一位置 重複步驟 3 直到某一指標達到序列尾 將另一串行剩下的所有元素直...