递归算法
将待排元素分成大小大致相同的两个子集合,分别对这两个集合进行排序,最终将排好序的子集合合并。
#include
#include
void Merge(int s[],int t[],int b,int m,int e){//将s[b...m]与s[m+1...e]合并
int i=b;//i->前一个块
int j=m+1;//j->后一个块
int k=0;//k->t数组
while(i<=m&&j<=e){
if(s[i]<=s[j])t[k++]=s[i++];
else t[k++]=s[j++];
}
while(i<=m){
t[k++]=s[i++];
}
while(j<=e){
t[k++]=s[j++];
}
for(int i=0;i
非递归算法
有三个函数:
(1)Merge函数,用于合并两个有序子段。这个函数主要是用于将a数组中[l,m]区间和[m+1,r]区间的数有序的合并到b数组的[l,r]区间。这里不同于递归方法里的Merge函数,b数组从l开始到r结束是有序的并且不用在Merge函数尾部将b数组的有序部分赋值给a数组(原因下面提到)。
(2)MergePass函数,这个函数的功能对于长为n数组进行归并,两个两个地合并长度为s的子段,当然我们的数组长度不可能每次正好满足“以s为子段长度时正好能两两合并,一个不多一个不少”。所以我们要对特殊情况进行判断:
while(i<=n-2*s){//剩下不超过2s长度的元素
Merge(x,y,i,i+s-1,i+2*s-1);
i=i+2*s;
}
在剩下的元素不能组成两个子段的时候分情况讨论:
a.当剩下元素可以凑成一个长为s子段,Merge(x,y,i,i+s-1,n-1);
b.当剩下元素连一个长为s的字段都凑不成时,我们直接将其略过(不排序)
(3)MergeSort函数,这个数组首先设一个临时数组b,与要归并的子段长度s,s初始为1,在s
#include
#include
#include
using namespace std;
void Merge(int a[],int b[],int l,int m,int r){
int i=l,j=m+1,k=l;
while(i<=m&&j<=r){
if(a[i]
自然合并排序
自然合并排序:对于初始给定的数组,通常存在多个长度大于1的已自然排好序的子数组段.例如,若数组a中元素为{4,8,3,7,1,5,6,2},则自然排好序的子数组段有{4,8},{3,7},{1,5,6},{2}.用一次对数组a的线性扫描就足以找出所有这些排好序的子数组段.然后将相邻的排好序的子数组段两两合并,构成更大的排好序的子数组段({3,4,7,8},{1,2,5,6}).继续合并相邻排好序的子数组段,直至整个数组已排好序.
所以我们可以设变量flag表示序列中有几段已经排好序的子段。
设数组t[flag]表示每个有序子段的第一个元素所在的位置。
代码如下:
#include
#include
#include
using namespace std;
int t[10],flag=0;
void Merge(int a[],int b[],int l,int m,int r){
int i=l,j=m+1,k=l;
while(i<=m&&j<=r){
if(a[i]
(第一行输出的是t数组,标记每个有序段的起始位置
第二行输出的是排好序的数组)