今天做了一道题,感想颇深
题目:交叉排序
蒜头君很无聊,现在有 N个数,其中第 i(1≤i≤N) 个数是 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上面的程序)