对冒泡法的深入研究

今天做了一道题,感想颇深

题目:交叉排序

蒜头君很无聊,现在有 N个数,其中第 i(1iN) 个数是 Ai

现在他先将 Al1,Al1+1...Ar1 从小到大排序。

再将 Al2,Al2+1...Ar2 从大到小排序。

请输出 A排序后的最终结果。

输入格式

第一行五个整数 N,l1,r1,l2,r2(l1<r1,l2<r2),均不超过 100000

第二行 N个不超过 int 范围的整数,表示 A数组。

输出格式

一行 N个用空格分隔的整数,表示 A排序以后的结果。

6 1 3 2 4
8 3 1 6 9 2
样例输出 1
1 8 6 3 9 2

之前是这样的:

#include<stdio.h>
int a[100000]={0};
int main()
{
	int N;
	int l1;//由小到大 
	int r1;
	int l2;//由大到小 
	int r2;
	int i=0;//循环变量 
	int j=0;//循环变量 
	int k=0;//循环变量 
	int temp;//转换变量 
	 /*输入*/
	scanf("%d%d%d%d%d",&N,&l1,&r1,&l2,&r2);
	for(i=0;i<N;i++)
	{
		scanf("%d",&a[i]);		
	}
	
	/*从小到大排序*/
	for(i=l1-1;i<r1-1;i++)
	{
		for(j=l1-1;j<r1-1-i;j++)
		{
			if(a[j]>a[j+1])
			{
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp; 
			}
		}
	} 
	/*用来检测第一次转换是否正确*/
		for(i=0;i<N;i++)
		{
			printf("%-5d",a[i]);	
		}
		printf("\n");	
	/*从大到小排序*/
	for(i=l2-1;i<r2-1;i++)
	{
		for(j=l2-1;j<r2-1-i;j++)
		{
			if(a[j]<a[j+1])
			{
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp; 
			}
		}
	}
	/*输出*/
	for(i=0;i<N;i++)
	{
		printf("%-5d",a[i]);	
	} 
	return 0;	
 } 

编译连接后:


跟样例答案不一致:

发现是第二次比较转换有问题,第3个数与第4个数有问题:

发现当第2个数与第3个比较:j=2-1;j<4-1-1;j++,即j=1;j<2;j++

            第2个数与第4个比较:j=2;j<4-1-1;j++,即j=2;j<2;j++,程序不符合,跳出

再j=r2-1-i后面加1就好了,发现不能广泛应用所以程序,j=3-1,4-1,后面应该加2,3才对

也就是说,当使用冒泡排序将极值放在后面,一趟比较后,后面的范围应该向前移动1个单位长度,而j=r2-1-i后面减的单位数字大于1,应该加上差值

排序修改后:

/*从小到大排序*/
	for(i=l1-1;i<r1-1;i++)
	{
		for(j=l1-1;j<r1-1-i+l1-1;j++)
		{
			if(a[j]>a[j+1])
			{
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp; 
			}
		}
	} 
	/*用来检测第一次转换是否正确*/
		for(i=0;i<N;i++)
		{
			printf("%-5d",a[i]);	
		}
		printf("\n");	
	/*从大到小排序*/
	for(i=l2-1;i<r2-1;i++)
	{
		for(j=l2-1;j<r2-1-i+l2-1;j++)
		{
			if(a[j]<a[j+1])
			{
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp; 
			}
		}
	}

编译运行:


最后结果跟例程答案一致

深度思考:

谭浩强的《C语言程序设计》中的冒泡排序,是输入10个数,从头到尾进行排序,即数组从0---9,相当于从一个到最后一个排序;for(i=0;i<9-j;i++)(

《C语言程序设计》第四版P148上面的程序第11行),因为j值为0,每次循环后j会自增1(上面的for循环的j加1),与逻辑的缩小范围值一致;而任意从某处到某处排序,根据教材的写法,后面缩小范围的表达式,后面减的不止是j值,后面还应该加上初始变量值(源代码:《C语言程序设计》第四版P148上面的程序)




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值