java 归并排序 非递归_归并排序三种实现方法(递归、非递归和自然合并排序)...

1.      递归实现归并排序

1)     基本思想:

将待排元素分成大小大致相同的2个子集,分别对2个子集合进行排序,最终将排好序的子集合合并 就会得到一个排好序的集合 即为所求

设归并排序的当前区间是R[low..high],分治法的三个步骤是:

① 分解:将当前区间一分为二,即求分裂点

② 求解:递归地对两个子区间R[low..mid]和R[mid+1..high] 进行归并排序;

③ 组合:将已排序的两个子区间R[low..mid]和R[mid+1..high] 归并为一个有序的区间R[low..high]。

递归的终结条件:子区间长度为1(一个记录自然有序)。

2)     具体过程如下图所示:

81135270_1.jpg

3)     代码实现

/*

数组a[]为待排序数组,数组b[]用来存放已排好序的数

left、right分别为待排序数组最左端和最右端的下标

mid为数组下标的中点

*/

#include

#include

using namespace std;

#define maxn 100

int  num[maxn];

//      将待排序集合一分为二,直至待排序集合只剩下一个元素为止,

//      然后不断合并两个排好序的数组段

template

void  MergeSort(Type a[],int left,int right)

{

Type *b=new Type [maxn];

if(left

{

int i=(left+right)/2;       //取数组中点,将数组尽量均等划分

MergeSort(a,left,i);        //将左半段进行递归排序

MergeSort(a,i+1,right);     //将右半段进行递归排序

Merge(a,b,left,i,right);    //合并到数组b

Copy(a,b,left,right);       //复制到数组a

}

}

//      将已排好序的数组合并到数组b[]中

template

void  Merge(Type a[],Type b[],int left,int mid,int right)

{

int i=left;

int j=mid+1;

int k=left;

while(i<=mid && j<=right)   //i的取值范围为 [left,m], j的取值范围为 [m+1,right]

{

if(a[i]

b[k++]=a[i++];

else

b[k++]=a[j++];

}

if(i>mid)                      //说明右边的数组的元素个数多

for(int z=j;z<=right;z++)

b[k++]=a[z];

else

for(int z=i;i<=mid;i++)

b[k++]=a[z];

}

//      将数组b[]中的数复制到数组a[]中

template

void  Copy(Type a[],Type b[],int left,int right)

{

for(int i=left;i<=right;i++)

a[i]=b[i];

}

int  main()

{

int n;

while(cin>>n)

{

for(int i=0;i

cin>>num[i];

MergeSort(num,0,n-1);

for(int i=0;i

cout<

}

system("pause");

return 0;

}

/*

7

49 38 65 97 76 13 27

*/

2.      非递归实现归并排序

1)   基本思想:

将数组中的相邻元素两两配对。用Merge()函数将他们排序,构成n/2组长度为2的排序好的子数组段,然后再将他们合并成长度为4的子数组段,如此继续下去,直至整个数组排好序

2)   具体过程如下图所示:

例1:8   3   2   6   7   1   5   4

81135270_2.jpg

例2:49   38   65  97   76   13   27

81135270_3.jpg

例2:49   38   65  97   76   (如上图)

3)   代码实现

#include

#include

using namespace std;

#define maxn 100

int num[maxn];

template

void MergeSort(Type c[],int n)

{

Type *d=new Type [n];

int  s=1;

while(s

{

MergePass(c,d,s,n);  //合并到数组d

s+=s;

MergePass(d,c,s,n);  //合并到数组c

s+=s;

}

}

//     合并大小为s的相邻子数组

template

void MergePass(Type x[],Type y[],int s,int n)

{

int i=0;

while(i+2*s-1

{

Merge(x,y,i,i+s-1,i+2*s-1);  //合并大小为s的相邻2段子数组

i+=2*s;

}

if(i+s

Merge(x,y,i,i+s-1,n-1);

else                              //剩下的元素个数m满足:m

for(int j=i;j<=n-1;j++)

y[j]=x[j];

}

template

void Merge(Type a[],Type b[],int left,int mid,int right)

{

int i=left;

int j=mid+1;

int k=left;

while(i<=mid && j<=right)

{

if(a[i]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值