归并排序–二路归并
eg:49 38 65 97 76 13 27
算法思想:
1、将原始序列看成7个只含有一个关键字的序列,所以这7个序列都是有序的(因为只有每个序列只有一个)
2、两两归并,形成若干个有序二元组,若没有归并对象,则保持原样
{38,49},{65,97},{13,76},{27};
3、再次两两合并得到如下序列
{38,49,65,79},{13,27,76};
4、再合并,即可得到最终排序结果
{13,27,38,49,65,76,79};
这个合并的过程其实和(两个递增链表合并为一个递增链表)的算法是一样
分组这个算法就是分治算法:先将整个序列分成两半, 对每一半进行归并排序,得到两个有序序列,最后再合并即为排序结果
#include<stdio.h>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
void merge(int a[],int left,int mid,int right)///合并操作
{
int L[100]= {0},R[100]= {0};
int n1=mid-left;
int n2=right-mid;
for(int k=0; k<n1; k++)///将整个序列分为两个序列L,R
L[k]=a[left+k];
for(int k=0; k<n2; k++)
R[k]=a[mid+k];
L[n1]=R[n2]=INF;///在L,R,末尾安插一个无穷大,防止两个标记相比较,
/// 又防止循环i,j 分别超过n1,n2;
int i=0,j=0;
for(int k=left; k<right; k++)///两个递增序列和并为一个序列保存在a中
{
if(L[i]<=R[j])
a[k]=L[i++];
else
a[k]=R[j++];
}
}
///分组过程
1、49 38 65 97 76 13 27
2、{49 38 65 97} {76 13 27}
3、{49 38} {65 97} {76,13} {27}
4、{49},{38},{65},{97},{76},{13},{27}
void mergesort(int a[],int left,int right)///left指开头,right指末尾加1
{
if(left+1<right)
{
int mid=(left+right)/2;
mergesort(a,left,mid);
mergesort(a,mid,right);
merge(a,left,mid,right);
}
}
int main()
{
int n;
int a[100];
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
mergesort(a,0,n);
for(int i=0; i<n; i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}