資料結構複習 歸併排序和基數排序

2021-08-03 20:54:54 字數 2276 閱讀 5138

歸併排序與基於交換、選擇等排序的思想不一樣,「歸併」的含義是將兩個或兩個以上的有序表組合成乙個新的有序表。假定待排序表含有n個記錄,則可以看成是n個有序的子表,每個子表長度為1,然後兩兩歸併,得到⌈n/2⌉個長度為2或1的有序表;再兩兩歸併,......如此重複,直到合併成乙個長度為n的有序表為止,這種排序方法稱為2-路歸併排序。

merge()的功能是將前後相鄰的兩個有序表歸併為乙個有序表的演算法。設兩段有序表a[low...mid]、a[mid+1...high]存放在同一順序表中相鄰的位置上,先將它們複製到輔助陣列b中。每次從對應b中的兩個段取出其對應的表長時(即該段的所有元素已經完全複製到a中),將另一段中的剩餘部分直接複製到a中。演算法如下:

elemtype *b=(elemtype *)malloc((n+1)*sizeof(elemtype)); 

void merge(elemtype a,int low,int mid,int high)

for(i=low,j=mid+1,k=i;i<=mid&&j<=high;k++)

while

(i<=mid)

a[k++]=b[i++];

while

(j<=high)

a[k++]=b[j++];

}

一趟歸併排序的操作是,呼叫到⌈n/2h⌉次演算法merge()將l[1...n]中前後相鄰且長度為h的有序段進行兩兩歸併,得到前後相鄰、長度為2h的有序段,整個歸併排序需要進行到⌈log2(n)⌉趟。

遞迴形式的2-路歸併排序演算法是基於分治的,其過程如下:

分解:將含有n個元素的待排序表分成各含有n/2個元素的子表,採用2-路歸併排序演算法對兩個子表遞迴地進行排序:

合併:合併兩個已排序的子表得到排序結果。

void

mergesort

(elemtype a,int low,int high)

}

2-路歸併排序演算法的效能分析如下:

空間效率:merge()操作中,輔助空間剛好占用n個單元,所以歸併排序的空間複雜度為o(n)。

時間效率:每一趟歸併的時間複雜度為o(n),共需要進行到⌈log2(n)⌉趟歸併,所以演算法的時間複雜度為o(nlog2(n))。

穩定性:由於merge()操作不會改變相同關鍵字記錄的相對次序,所以2-路歸併排序演算法是乙個穩定的排序演算法。

基數排序是一種很特殊的排序方法,它不是基於比較進行排序的,而是採用多關鍵字排序思想(即基於關鍵字各位的大小進行排序的),借助「分配」和「收集」兩種操作對單邏輯關鍵字進行排序。基數排序又分為最高位優先(msd)排序和最低位優先(lsd)排序。

以lsd為例,假設原來有一串數值如下所示:

73, 22, 93, 43, 55, 14, 28, 65, 39, 81

首先根據個位數的數值,在走訪數值時將它們分配至編號0到9的桶子中:

01 81

2 22

3 73 93 43

4 14

5 55 6567

8 28

9 39

接下來將這些桶子中的數值重新串接起來,成為以下的數列:

81, 22, 73, 93, 43, 14, 55, 65, 28, 39

接著再進行一次分配,這次是根據十位數來分配:

01 14

2 22 28

3 39

4 43

5 55

6 65

7 73

8 81

9 93

接下來將這些桶子中的數值重新串接起來,成為以下的數列:

14, 22, 28, 39, 43, 55, 65, 73, 81, 93

這時候整個數列已經排序完畢;如果排序的物件有三位數以上,則持續進行以上的動作直至最高位數為止。

lsd的基數排序適用於位數小的數列,如果位數多的話,使用msd的效率會比較好。msd的方式與lsd相反,是由高位數為基底開始進行分配,但在分配之後並不馬上合併回乙個陣列中,而是在每個「桶子」中建立「子桶」,將每個桶子中的數值按照下一數字的值分配到「子桶」中。在進行完最低位數的分配後再合併回單一的陣列中。

基數排序演算法的效能分析如下:

空間效率:一趟排序需要的輔助儲存空間為r(r個佇列),但以後的排序中重複使用這些佇列,所以基數排序的空間複雜度為o(r)。

時間效率:基數排序需要進行d趟分配和收集,一趟分配需要o(n),一趟收集需要o(r),所以基數排序的時間複雜度為o(d(n+r)),它與序列的初始化狀態無關。

穩定性:對於基數排序演算法而言,很重要一點就是按位排序時必須是穩定的。因此,這也保證了基數排序保持穩定性。

資料結構 歸併排序 基數排序

1.歸併排序 是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。將已有序的子串行合併,得到完全有序的序列 即先使每個子串行有序,再使子串行段間有序。若將兩個有序表合併成乙個有序表,稱為二路歸併。例 設有數列 初始狀態 6,20...

歸併排序和基數排序

空間複雜度 o n o n o n 時間複雜度 o n log2 n o nlog 2n o nlog 2 n 穩定性 穩定 適用於順序儲存和鏈式儲存 typedef int elemtype 合併兩個相鄰的有序線性表 void merge elemtype a,int low,int mid,in...

11 歸併排序和基數排序

核心思想 拆分和合併,拆分其實只幹了一件事將陣列2等份,一直拆分到無法拆分為止,合併在於從最小拆分單元先排序,然後向上合併再排序,最終得到乙個有序陣列。分支演算法採用的遞迴操作,核心 在於合併。public class mergesort int temp newint arr.length mer...