归并排序非递归算法最通俗易懂的解析

分析:

非递归,即迭代,与递归最大的区别在于实现的方向不同。递归拆开来是“递推”与“回归”,也就是先从顶层往下,逐层递推到底层,再从底层逐层回归到顶层,所以mergesort的递归版本是先从顶层开始往下不断对数组一分为二,到底层归并,回到上一层,再归并,重复直到顶层。非递归是从底层开始不断往上迭代,mergesort的迭代版本是从底层开始,对左边k个右边k个元素归并,换下一段,再对左右两边k个元素局部归并,直到数组末尾,如果有剩余,最后再归并左边k个和右边剩余的元素一次,k乘以2,这样算一次迭代,下一次遍历数组,对2k个元素局部归并,直到nk不小于数组长度,到达顶层,结束。

代码:

#include<iostream>

#include<cstdlib>

#define SIZE 30

#define RANDOM 100

using namespace std;

int *b=new int[SIZE];//开头先定义临时数组

void MergeNonRec(int *elem,int lo,int mi,int hi)

{//对elem数组的[lo,mi),[mi,hi)部分合并,注意右边是开区间

int lb=mi-lo;

int lc=hi-mi;

int *a=elem+lo;//a从elem的lo开始改变elem

int *c=elem+mi;//c从elem+mi开始到elem+hi的部分将与elem+lo到elem+mi作对比

for(int i=0;i<lb;b[i]=a[i++]);//b接收elem+lo到elem+mi的部分与c对比

for(int i=0,j=0,k=0;j<lb||k<lc;)//b与c对比完存入a

{

if(j<lb&&(lc<=k||b[j]<c[k]))a[i++]=b[j++];

if(k<lc&&(lb<=j||c[k]<=b[j]))a[i++]=c[k++];

}

}

void MergePass(int *elem,int k,int len)

{

int i=0;

while(i+2*k<=len)//遍历数组

{

MergeNonRec(elem,i,i+k,i+2*k);//每次对左边k个和右边k个元素归并

i+=2*k;//合并完两个k个元素的部分后,指针位移2k个单位

}

if(i+k<=len)//若有剩余数据则将剩余部分再归并一次,即左边k个右边len-i-k个

MergeNonRec(elem,i,i+k,len);

}

void MergeSortNonRec(int *elem,int len)

{

int k=1;//定义步长,即合并元素个数

while(k<len)

{

MergePass(elem,k,len);//遍历数组并局部归并k个元素,即左边k个右边k个

k*=2;//两端的k个元素归并完,再对两端2k个元素归并

}

}

int main()

{

srand(time(NULL));

int a[SIZE];

for(int i=0;i<SIZE;i++)

a[i]=rand()%RANDOM;

cout<<"Before:";

cout<<a[0];

for(int i=1;i<SIZE;i++)

cout<<' '<<a[i];

MergeSortNonRec(a,SIZE);

cout<<"After:";

cout<<a[0];

for(int i=1;i<SIZE;i++)

cout<<' '<<a[i];

cout<<endl;

return 0;

}

归并排序非递归算法最通俗易懂的解析

相关推荐