【筆記】歸併排序
歸併排序:是又一類不同的排序方法。“歸併”的含義是將兩個或兩個以上的有序表組合成一個新的有序表。無論是順序儲存結構還是連結串列儲存結構,都可在
O(m+n)
的時間量級上實現。
基本演算法思想:假設初始序列含有n個記錄,則可看成是n個有序的子序列,每個子序列的長度為1,然後兩兩歸併,得到
[n2] [\frac{n}{2}]個長度為2或1的有序子序列,再兩兩歸併……如此重複,直至得到一個長度為n的有序序列為止,這種排序方法稱為2-路歸併排序。
一趟歸併排序的操作是,呼叫
[ \frac{n}{2h}]
次演算法merge將SR.[1…n]中前後相鄰且長度為h的有序段進行兩兩歸併,得到前後相鄰、長度為2h的有序段,並存放在TR.[1…n]中,整個歸併排序需進行[log_2 n]
趟。可見,實現歸併排序需和待排記錄等數量的輔助空間,其時間複雜度為O(nlogn)
。
遞迴形式的演算法在形式上較簡潔,但是實用性很差。與快速排序和堆排序相比,歸併排序的最大特點是:它是一種穩定的排序方法。但在一般情況下,很少使用2-路歸併排序法進行內部排序。
2-路歸併排序中的核心操作是將一維陣列中前後相鄰的兩個有序序列歸併為一個有序序列,其演算法如下所示。
- 型別定義
#include<stdio.h>
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)<=(b))
#define N 7
#define MAXSIZE 20 /* 一個用作示例的小順序表的最大長度 */
typedef int InfoType; /* 定義其它資料項的型別 */
typedef int KeyType; /* 定義關鍵字型別為整型 */
typedef struct
{
KeyType key; /* 關鍵字項 */
InfoType otherinfo; /* 其它資料項,具體型別在主程中定義 */
}RedType; /* 記錄型別 */
typedef struct
{
RedType r[MAXSIZE+1]; /* r[0]閒置或用作哨兵單元 */
int length; /* 順序表長度 */
}SqList; /* 順序表型別 */
- 歸併排序函式
void Merge(RedType SR[],RedType TR[],int i,int m,int n)
{ /* 將有序的SR[i..m]和SR[m+1..n]歸併為有序的TR[i..n] 演算法10.12 */
int j,k,l;
for(j=m+1,k=i;i<=m&&j<=n;++k) /* 將SR中記錄由小到大地併入TR */
if LQ(SR[i].key,SR[j].key)
TR[k]=SR[i++];
else
TR[k]=SR[j++];
if(i<=m)
for(l=0;l<=m-i;l++)
TR[k+l]=SR[i+l]; /* 將剩餘的SR[i..m]複製到TR */
if(j<=n)
for(l=0;l<=n-j;l++)
TR[k+l]=SR[j+l]; /* 將剩餘的SR[j..n]複製到TR */
}
void MSort(RedType SR[],RedType TR1[],int s, int t)
{ /* 將SR[s..t]歸併排序為TR1[s..t]。演算法10.13 */
int m;
RedType TR2[MAXSIZE+1];
if(s==t)
TR1[s]=SR[s];
else
{
m=(s+t)/2; /* 將SR[s..t]平分為SR[s..m]和SR[m+1..t] */
MSort(SR,TR2,s,m); /* 遞迴地將SR[s..m]歸併為有序的TR2[s..m] */
MSort(SR,TR2,m+1,t); /* 遞迴地將SR[m+1..t]歸併為有序的TR2[m+1..t] */
Merge(TR2,TR1,s,m,t); /* 將TR2[s..m]和TR2[m+1..t]歸併到TR1[s..t] */
}
}
void MergeSort(SqList *L)
{ /* 對順序表L作歸併排序。演算法10.14 */
MSort((*L).r,(*L).r,1,(*L).length);
}
- 主程式
void print(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
printf("(%d,%d)",L.r[i].key,L.r[i].otherinfo);
printf("\n");
}
void main()
{
RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7}};
SqList l;
int i;
for(i=0;i<N;i++)
l.r[i+1]=d[i];
l.length=N;
printf("排序前:\n");
print(l);
MergeSort(&l);
printf("排序後:\n");
print(l);
}
- 測試結果
相關文章
- 歸併排序排序
- (戀上資料結構筆記):歸併排序(Merge Sort)資料結構筆記排序
- 快速排序&&歸併排序排序
- 四、歸併排序 && 快速排序排序
- java歸併排序Java排序
- 《演算法筆記》3. 歸併排序、隨機快排整理演算法筆記排序隨機
- 排序演算法__歸併排序排序演算法
- 排序演算法:歸併排序排序演算法
- 排序演算法 - 歸併排序排序演算法
- 排序演算法(歸併排序)排序演算法
- 歸併排序--排序演算法排序演算法
- 歸併排序--二路排序排序
- 歸併排序和基數排序排序
- 歸併排序 js demo排序JS
- 排序演算法之 '歸併排序'排序演算法
- php實現 歸併排序,快速排序PHP排序
- php插入排序,快速排序,歸併排序,堆排序PHP排序
- 歸併排序 nO(lgn) 稽核中排序
- 歸併排序——C語言排序C語言
- go 實現歸併排序Go排序
- 歸併排序加例題排序
- 氣泡排序、歸併排序與快速排序比較排序
- 手寫演算法並記住它:歸併排序演算法排序
- 歸併排序 2020-09-20排序
- 演算法之歸併排序演算法排序
- 使用 Swift 實現歸併排序Swift排序
- 歸併排序的簡單理解排序
- 演算法:排序連結串列:歸併排序演算法排序
- 排序演算法之「歸併排序(Merge Sort)」排序演算法
- BAT 經典演算法筆試題 —— 磁碟多路歸併排序BAT演算法筆試排序
- 淺談歸併排序:合併 K 個升序連結串列的歸併解法排序
- 演算法(氣泡排序,快排,歸併排序)演算法排序
- 演算法學習 – 歸併排序演算法排序
- HDU 2689 【歸併排序求逆序對】排序
- 演算法學習 - 歸併排序演算法排序
- 歸併排序(C++_分治遞迴)排序C++遞迴
- 歸併排序MergeSort的C實現排序
- 歸併排序就這麼簡單排序
- rust-algorithms:9-歸併排序RustGo排序