非递归实现归并排序

记录刚学习的非递归实现归并排序

由于初学,把自已一些对编码的理解记录下来

不足的地方欢迎大家指正

非递归实现归并的基本原理:

            对于一个数组{26,5,77,1,61,11,59,15,48,19}

如上图所示,我们所要实现上图的模型:

         一是要比较每两个数组所含值的大小关系,从而排序成一个有序的且含那两个数组的大数组

         ({26},{5}->{5,26}          {5,26},{1,77}->{1,5,26,77})

         二是如何将两个小数组归并为一个大数组     

 对于第一个问题:

存在两个数组{1,5,26,77}与{11,15,59,61}和一个临时数组num[ ]

        用i来代替第一个数组的元素1

        用j来代替第二个数组的元素11

        用k来代表num中的第一个元素

        先来比较两个数组的第一个元素,

        如果i<j,则i++,k++

        如果j<i,则j++,k++

        直至一个数组中的元素全部赋到num[ ]中,则把另一数组的元素依次赋到num[ ]中

同理,在一个数组中,我们用3个变量将一个数组分割

         {26,5,77,1,61,11,59,15,48,19}

        left=26,mid=61,right=19

        此时left->mid代表{26,5,77,1,61}

        mid+1->right代表{11,59,15,48,19}

void merge(int SR[],int QR[],int left,int mid,int right)
{
	int i,j,k,L;/*SR[]是传递下来的原数组,QR是归并后的新数组*/
                /*i记录从left->mid*/
				/*j记录从mid+1->right*/
				/*k记录两个数组归并后的数组*/
				/*L用用于把剩余的一个数组的值依次补录入新数组中*/
	
	
	for(i=left,j=mid+1,k=left;i<=mid&&j<=right;k++)
	{
	
		if(SR[i]<SR[j])
			QR[k]=SR[i++];
		else
			QR[k]=SR[j++];
	}
	if(i<=mid)
	{
		for(L=0;L<=mid-i;L++)
			QR[k+L]=SR[i+L];
	}else
	{
		for(L=0;L<=right-j;L++)
			QR[k+L]=SR[j+L];
	}

对于第二个问题:

      (1)  可以通过循环来表示所分块的大小

for(s=1;s<max;s*=2) /*max代表数组的最大范围*/
{

}

 所以第一次循环,s=1,即每个元素都作为一个数组

第二次循环,s=s*2=2,即两个元素作为一个数组

……

(2)找到每个数组开始的元素下表与结束下标

      ①  用i来代表原数组的第一个元素下标(i=0),当s=1时                         (每个元素内涵一个值

        left=i=0        mid=i+s-1=0        mid+1=1        right=i+2*s-1=1     此时表示第一个和第二个元素

        i=i+2*s= 2

        left=i=2        mid=i+s-1=2        mid+1=3        right=i+2*s-1=3      此时表示第三个与第四个元素

        i=i+2*s=4

        left=i=4        mid=i*s-1=4        mid+1=5        right=i+2*s-1=5      此时表示第五个与第六个元素

        …………

       ② 当s=2时(此时i又重置为0)

        left=i=0        mid=i+s-1=1        mid+1=2        right=i+2*s-1=3       

       此时表示第一个元素与第二个元素(每个元素内涵2个值

        …………

        当s>=max时(max为数组所含元素的个数)结束

#include <stdlib.h>

void merge(int SR[],int QR[],int left,int mid,int right);

int main()
{
	int s,i,j;
	int *TR=(int*)malloc(10*sizeof(int));/*创建一个临时储存空间*/
	int num[10]={8,6,1,7,5,9,3,4,5,2};
    int n=9/*n为数组最后一个元素的下标*/
	for(s=1;s<10;s*=2)
	{
		i=0;
		while(i<n-2*s+1)     /*----------①*/
		{
			merge(num,TR,i,i+s-1,i+2*s-1);
			i=i+2*s;
		}
		
		if(i<n-s+1)          /*--------②*/
			merge(num,TR,i,i+s-1,n);
		 else 
			for(j=i;j<=n;j++)/*----------③*/
				TR[j]=num[j];
		for(i=0;i<10;i++)   /*----------④*/
			num[i]=TR[i];		
	}

①是对不同层数组末尾的判断,其实是  (right<n)        ==        (i+2*s-1<n)        ==        (i<n-2*s+1)

②是对所剩元素为双的判断,其实是 (mid<n)

③是为所剩元素为单的判断,并将所剩元素插入新数组中

④是记录每一次循环所产生的新的数组TR,并将值赋予num,然后num继续被merge函数调用

否则一直调用的是原本的未排序的num!!!

 下面是两部分之和

#include <stdlib.h>

void merge(int SR[],int QR[],int left,int mid,int right);

int main()
{
	int s,i,j;
	int *TR=(int*)malloc(10*sizeof(int));
	int n=9;
	int num[10]={8,6,1,7,5,9,3,4,5,2};
	for(s=1;s<10;s*=2)
	{
		i=0;
		while(i<n-2*s+1) 
		{
			merge(num,TR,i,i+s-1,i+2*s-1);
			i=i+2*s;
		}
		
		if(i<n-s+1)
			merge(num,TR,i,i+s-1,n);
		 else 
			for(j=i;j<=n;j++)
				TR[j]=num[j];
		for(i=0;i<10;i++)
			num[i]=TR[i];		
	}
	for(i=0;i<10;i++)
	{
		
		printf("%d",num[i]);     /*加入printf用来输出*/
	}
	return 0;
}
void merge(int SR[],int QR[],int left,int mid,int right)
{
	int i,j,k,L;
	
	for(i=left,j=mid+1,k=left;i<=mid&&j<=right;k++)
	{
		if(SR[i]<SR[j])
			QR[k]=SR[i++];
		else
			QR[k]=SR[j++];
	}
	if(i<=mid)
	{
		for(L=0;L<=mid-i;L++)
			QR[k+L]=SR[i+L];
	}else
	{
		for(L=0;L<=right-j;L++)
			QR[k+L]=SR[j+L];
	}
	
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值