複習資料結構:排序演算法(四)——歸併排序
基本思想:基於分治法,即把待排序的陣列序列,分為若干個子序列,對每個子序列排序,然後再把所有有序的子序列合併為一個整體有序的序列。分析可知,如果拿任何一個元素作為子序列,那麼所有子序列就已經是有序的,而歸併排序的關鍵就在於如何合併,也就是“歸併”。
歸併排序是外排序,穩定排序,時間複雜度是O(nlogn).
![](https://i.iter01.com/images/db6c168f741662891f48b8b439c658cd5cb0cb4fa65254b89a21d88bc945ec1f.png)
詳細說歸併排序的過程:1個元素的表總是有序的。所以對n個元素的待排序列,每個元素可看成1個有序子表。對子表兩兩合併生成n/2個子表,所得子表除最後一個子表長度可能為1 外,其餘子表長度均為2。再進行兩兩合併,直到生成n 個元素按關鍵碼有序的表。
程式碼如下:
非遞迴實現:(經過除錯,該程式有bug,後續修正!)
#include<iostream>
using namespace std;
void Merge(int* r, int* rf, int i, int m, int n)
{
int j, k;
for(j = m+1, k = i; i <= m && j <= n; k++) // i記錄第一個子序列標記,j記錄第二個子序列標記,k記錄合併後序列標記
{
if(r[j] < r[i]) // 存入較小者
rf[k] = r[j++];
else
rf[k] = r[i++];
}
while(i <= m) // 如果不等長,就會出現這種情況
rf[k++] = r[i++];
while(j <= n)
rf[k++] = r[j++];
for(int ii = 0; ii < n+1; ii++)
cout<<rf[ii]<<' ';
cout<<endl;
}
void MergeSort(int* r, int* rf, int length)
{
int len = 1;
int* q = r;
//int* tmp;
while(len < length)
{
int s = len;
len = 2*s; // 等長的兩個子序列,長度相同
int i = 0;
bool flag = true;
while(i + len <= length) // 等長的兩個子序列合併
{
cout<<"等長"<<i<<'-'<<i+s-1<<'-'<<i+len-1<<endl;
Merge(q, rf, i, i+s-1, i+len-1); // 注意起始位置的標記
i += len; // 下一次合併的起始
flag = false;
}
if(i + s <= length) // 不等長兩個子序列合併
{
cout<<"不等長"<<i<<'-'<<i+s-1<<'-'<< length-1<<endl;
Merge(q, rf, i, i+s-1, length-1); // 注意最後的結束標記位置
}
cout<<"flag="<<flag<<endl;
if(!flag)
swap(q, rf); // 交換指標,該次合併的結果作為下次合併的起始
}
}
int main()
{
int a[10] = {11,1,5,7,2,4,9,6,10}; // ,9,6,10,8
int b[10];
MergeSort(a, b, 9);
for(int i = 0; i< 9; i++)
cout<<b[i]<<' ';
cout<<endl;
return 0;
}
遞迴實現:
void MSort(ElemType *r, ElemType *rf,int s, int t)
{
ElemType *rf2;
if(s==t) r[s] = rf[s];
else
{
int m=(s+t)/2; /*平分*p 表*/
MSort(r, rf2, s, m); /*遞迴地將p[s…m]歸併為有序的p2[s…m]*/
MSort(r, rf2, m+1, t); /*遞迴地將p[m+1…t]歸併為有序的p2[m+1…t]*/
Merge(rf2, rf, s, m,t); /*將p2[s…m]和p2[m+1…t]歸併到p1[s…t]*/
}
}
void MergeSort_recursive(ElemType *r, ElemType *rf, int n)
{ /*對順序表*p 作歸併排序*/
MSort(r, rf,0, n-1);
}
參考:
http://blog.csdn.net/xiazdong/article/details/8462393
http://blog.csdn.net/hguisu/article/details/7776068
http://blog.csdn.net/jetjetlinuxsystem/article/details/6589093
相關文章
- 資料結構與演算法——排序演算法-歸併排序資料結構演算法排序
- 【資料結構與演算法】歸併排序資料結構演算法排序
- 演算法與資料結構高階排序演算法之歸併排序演算法資料結構排序
- 資料結構:歸併排序(非遞迴)資料結構排序遞迴
- 四、歸併排序 && 快速排序排序
- 演算法:排序連結串列:歸併排序演算法排序
- 演算法與資料結構系列 ( 七 ) - 歸併排序- Merge Sort演算法資料結構排序
- 排序演算法__歸併排序排序演算法
- 排序演算法:歸併排序排序演算法
- 排序演算法 - 歸併排序排序演算法
- 排序演算法(歸併排序)排序演算法
- 歸併排序--排序演算法排序演算法
- 【Java資料結構與演算法】第八章 快速排序、歸併排序和基數排序Java資料結構演算法排序
- 排序演算法之 '歸併排序'排序演算法
- 演算法學習 – 歸併排序演算法排序
- 演算法學習 - 歸併排序演算法排序
- 【資料結構與演算法】高階排序(希爾排序、歸併排序、快速排序)完整思路,並用程式碼封裝排序函式資料結構演算法排序封裝函式
- (戀上資料結構筆記):歸併排序(Merge Sort)資料結構筆記排序
- 排序演算法之「歸併排序(Merge Sort)」排序演算法
- 快速排序&&歸併排序排序
- 演算法之歸併排序演算法排序
- 演算法之常見排序演算法-氣泡排序、歸併排序、快速排序演算法排序
- 重學資料結構和演算法(四)之氣泡排序、插入排序、選擇排序資料結構演算法排序
- 演算法(氣泡排序,快排,歸併排序)演算法排序
- 歸併排序排序
- 資料結構與演算法——排序演算法-基數排序資料結構演算法排序
- 資料結構與演算法——排序演算法-氣泡排序資料結構演算法排序
- 資料結構與演算法——排序演算法-選擇排序資料結構演算法排序
- 從零開始學資料結構和演算法 (五) 分治法 (二分查詢、快速排序、歸併排序)資料結構演算法排序
- 資料結構與演算法——排序資料結構演算法排序
- 【資料結構與演算法】非比較排序(計數排序、桶排序、基數排序)資料結構演算法排序
- 歸併排序--二路排序排序
- 歸併排序和基數排序排序
- php插入排序,快速排序,歸併排序,堆排序PHP排序
- java歸併排序Java排序
- 資料結構與演算法(八):排序資料結構演算法排序
- 資料結構與演算法之排序資料結構演算法排序
- 資料結構與演算法:堆排序資料結構演算法排序
- 【資料結構與演算法】堆排序資料結構演算法排序