参考:http://blog.csdn.net/prstaxy/article/details/8166360
归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的,然后再把有序子序列合并为整体有序序列。
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
时间复杂度为O(nlogn),空间复杂度为 O(n),归并排序比较占用内存,但却效率高且是稳定的算法。
下面的代码是递归和非递归的实现。
#include<iostream>
using namespace std;
void printArray(int data[],int size);
void merge(int data[], int low,int mid, int high) //两个有序子序列合并
{
//子序列1:数组下标low到mid
//子序列2:数组下标mid+1到high
int *temp=new int[high-low+1];
int i=low, j=mid+1, ti=0; //ti:合并后temp数组的下标
if(temp==NULL)
{
cout<<"内存分配失败"<<endl;
}
printf("对下标%d--%d--%d 数字%d--%d排序\n",low,mid,high,data[low],data[high]);
while(i<=mid && j<=high)
{
if(data[i]<data[j])
{
cout<<data[i]<<"<"<<data[j]<<endl;
temp[ti++]=data[i++];
}
else
{
cout<<data[j]<<"<"<<data[i]<<endl;
temp[ti++]=data[j++];
}
}
while(i<=mid) //若序列1还有剩余,将剩余元素放入新数组中
temp[ti++]=data[i++];
while(j<=high) //若序列2还有剩余,将剩余元素放入新数组中
temp[ti++]=data[j++];
for(ti=0;ti<high-low+1;ti++) //将排序后的数组元素,放入原数组中相应的位置
data[low+ti]=temp[ti];
delete[] temp;
}
//<span style="color: rgb(54, 46, 43); font-family: Arial; font-size: 14px; line-height: 26px;">递归的合并排序,如果子数组中至多有一个元素,当然是已排好,否则分解</span>
void mergeSort(int data[], int low, int high) //递归实现归并排序
{
if(low<high) //不少于2个元素,进行合并
{
int mid=(low+high)/2;
mergeSort(data,low,mid); //拆分左边子序列
mergeSort(data,mid+1,high); //拆分右边子序列
merge(data,low,mid,high); //合并
printArray(data,9);
}
}
void mergeSort(int data[], int n) //非递归实现排序,基本思想是:两两合并
{
int step=1; //步长2的指数增长1,2,4,8,16....
int i;
while(step<=n)
{
int low=0; //每次对整个数组合并前,low=0;从头开始
printf("step=%d\n",step);
while(low<=n-1)
{
int mid=low+step-1;
int high=mid+step;
if(high>=n) //high下标判断
high=n-1;
if(mid>high) //mid下标判断
mid=high;
merge(data,low,mid,high);
low=high+1;
}
printArray(data,9);
step=step*2;
}
}
void printArray(int data[],int size)
{
int i;
for(i=0;i<size;i++)
cout<<data[i]<<" ";
cout<<endl;
}
int main()
{
int data[9]={5,3,6,2,1,9,4,8,7};
cout<<"排序前:"<<endl;
printArray(data,9);
cout<<"排序过程:"<<endl;
mergeSort(data,0,8); //递归
//mergeSort(data,9); //非递归
}
递归结果:
排序前:
5 3 6 2 1 9 4 8 7
排序过程:
对下标0--0--1 数字5--3排序
3<5
3 5 6 2 1 9 4 8 7
对下标0--1--2 数字3--6排序
3<6
5<6
3 5 6 2 1 9 4 8 7
对下标3--3--4 数字2--1排序
1<2
3 5 6 1 2 9 4 8 7
对下标0--2--4 数字3--2排序
1<3
2<3
1 2 3 5 6 9 4 8 7
对下标5--5--6 数字9--4排序
4<9
1 2 3 5 6 4 9 8 7
对下标7--7--8 数字8--7排序
7<8
1 2 3 5 6 4 9 7 8
对下标5--6--8 数字4--8排序
4<7
7<9
8<9
1 2 3 5 6 4 7 8 9
对下标0--4--8 数字1--9排序
1<4
2<4
3<4
4<5
5<7
6<7
1 2 3 4 5 6 7 8 9
请按任意键继续. . .
非递归结果:
排序前:
5 3 6 2 1 9 4 8 7
排序过程:
step=1
对下标0--0--1 数字5--3排序
3<5
对下标2--2--3 数字6--2排序
2<6
对下标4--4--5 数字1--9排序
1<9
对下标6--6--7 数字4--8排序
4<8
对下标8--8--8 数字7--7排序
3 5 2 6 1 9 4 8 7
step=2
对下标0--1--3 数字3--6排序
2<3
3<6
5<6
对下标4--5--7 数字1--8排序
1<4
4<9
8<9
对下标8--8--8 数字7--7排序
2 3 5 6 1 4 8 9 7
step=4
对下标0--3--7 数字2--9排序
1<2
2<4
3<4
4<5
5<8
6<8
对下标8--8--8 数字7--7排序
1 2 3 4 5 6 8 9 7
step=8
对下标0--7--8 数字1--7排序
1<7
2<7
3<7
4<7
5<7
6<7
7<8
1 2 3 4 5 6 7 8 9
请按任意键继续. . .