歸併排序是建立在歸併操作上的一種有效的排序算法,該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱爲二路歸併。
看到一篇博客講的蠻好的,動態圖很生動,下面是鏈接:
http://blog.csdn.net/wu_lai_314/article/details/8450933
博主同時還在另外一篇博文中介紹了一種改進算法,不過代碼雖然能得到正確結果,但是由於程序邏輯不對,實際排序是通過插入排序法進行排序的,其歸併排序算是繞了一圈沒有解決問題。其鏈接如下:
http://blog.csdn.net/wu_lai_314/article/details/8452526
這裏是我進行修改後的代碼:
#define M 16
#include<iostream>
#include <time.h>
#include<iomanip>
using namespace std;
void insertSort(int *a, int left, int right){
int tmp;
int i, j;
for (i = left + 1; i <= right; i++){//外層循環是從第二個元素開始的
if (a[i]<a[i - 1]){
tmp = a[i];
j = i - 1;
do{
a[j + 1] = a[j--];
} while (j >= left && tmp < a[j]);
a[j + 1] = tmp;
}
}
}
void improvedMerge(int *a, int left, int mid, int right){
int s1 = left;//s1,s2 是檢測指針,t是存放指針
int s2 = right;
int t = left, k;
int *b = new int[right];
for (k = left; k <= mid; k++)//正向複製
b[k] = a[k];
for (k = mid + 1; k <= right; k++)//反向複製
b[right + mid + 1 - k] = a[k];
while (t <= right){//歸併過程
if (b[s1] <= b[s2]) a[t++] = b[s1++];
else a[t++] = b[s2--];
}
}
void doSort(int *a, int left, int right){
if (left >= right) return;
if (right - left + 1 < M)
{
insertSort(a, left, right);//序列長度小於M時候,進行插入排序,再跳出循環
return;
}
int mid = (left + right) / 2;//從中間劃分兩個子序列
doSort(a, left, mid);//從左側子序列進行遞歸排序
doSort(a, mid + 1, right);//從右側子序列進行遞歸排序
improvedMerge(a, left, mid, right);//合併
}
void main(){
int a[100];
srand((unsigned int)time(NULL));
for (int i = 0; i<100; i++)
a[i] = rand();
doSort(a, 0, 99);
for (int i = 0; i<100; i++){
if (i % 7 == 0 && i != 0)
cout << endl;
cout << setw(10) << a[i] << " ";
}
cout << endl;
getchar();
}