c語言算法 - 分而治之算法 - 歸併排序

能夠運用分而治之方法來解決排序問題,該問題是將n個元素排成非遞減順序。分而治之方法一般用如下的步驟來進行排序算法:若n 爲1,算法終止;不然,將這一元素集合分割成兩個或更多個子集合,對每個子集合分別排序,而後將排好序的子集合歸併爲一個集合。
假設僅將n個元素的集合分紅兩個子集合。如今須要肯定如何進行子集合的劃分。一種可能性就是把前面n- 1個元素放到第一個子集中(稱爲A),最後一個元素放到第二個子集裏(稱爲B)。按照這種方式對A遞歸地進行排序。因爲B僅含一個元素,因此它已經排序完畢,在A排完序後,只須要用程序2 - 1 0中的函數i n s e r t將A和B合併起來。把這種排序算法與I n s e r t i o n S o r t(見程序2 - 1 5)進行比較,能夠發現這種排序算法實際上就是插入排序的遞歸算法。該算法的複雜性爲O (n 2 )。把n個元素劃分紅兩個子集合的另外一種方法是將含有最大值的元素放入B,剩下的放入A中。而後A被遞歸排序。爲了合併排序後的A和B,只須要將B添加到A中便可。假如用函數M a x(見程序1 - 3 1)來找出最大元素,這種排序算法實際上就是S e l e c t i o n S o r t(見程序2 - 7)的遞歸算法。
假如用冒泡過程(見程序2 - 8)來尋找最大元素並把它移到最右邊的位置,這種排序算法就是B u b b l e S o r t(見程序2 - 9)的遞歸算法。這兩種遞歸排序算法的複雜性均爲(n2 )。若一旦發現A已經被排好序就終止對A進行遞歸分割,則算法的複雜性爲O(n2 )(見例2 - 1 6和2 - 1 7)。
上述分割方案將n個元素分紅兩個極不平衡的集合A和B。A有n- 1個元素,而B僅含一個元素。下面來看一看採用平衡分割法會發生什麼狀況: A集合中含有n/k個元素,B中包含其他的元素。遞歸地使用分而治之方法對A和B進行排序。而後採用一個被稱之爲歸併( m e rg e)的過程,將已排好序的A和B合併成一個集合。
例2-5 考慮8個元素,值分別爲[ 1 0,4,6,3,8,2,5,7 ]。若是選定k = 2,則[ 1 0 , 4 , 6 , 3 ]和[ 8 , 2 , 5 , 7 ]將被分別獨立地排序。結果分別爲[ 3 , 4 , 6 , 1 0 ]和[ 2 , 5 , 7 , 8 ]。從兩個序列的頭部開始歸併這兩個已排序的序列。元素2比3更小,被移到結果序列;3與5進行比較,3被移入結果序列;4與5比較,4被放入結果序列;5和6比較,.。若是選擇k= 4,則序列[ 1 0 , 4 ]和[ 6 , 3 , 8 , 2 , 5 , 7 ]將被排序。排序結果分別爲[ 4 , 1 0 ]和[ 2 , 3 , 5 , 6 , 7 , 8 ]。當這兩個排好序的序列被歸併後,便可得所須要的排序序列。
圖2 - 6給出了分而治之排序算法的僞代碼。算法中子集合的數目爲2,A中含有n/k個元素。
template
void sort( T E, int n)
{ / /對E中的n個元素進行排序,k爲全局變量
if (n >= k) {
i = n/k;
j = n-i;
令A 包含E中的前i個元素
令B 包含E中餘下的j個元素
s o r t ( A , i ) ;
s o r t ( B , j ) ;
m e rge(A,B,E,i,j,); //把A 和B 合併到E
}
else 使用插入排序算法對E 進行排序
}
圖14-6 分而治之排序算法的僞代碼
相關文章
相關標籤/搜索