归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(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();
}