4.有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中。
- #include <stdio.h>
- int main( )
- { int a[11]={1,4,6,9,13,15,19,18,40,100};
- int temp1,temp2,number,end,i,j;
- printf("array a:\n");
- for(i=0;i<10;i++)
- printf("%5d",a[ i ]);
- printf("\n");
- printf("insert data:");
- scanf("%d",&number);
- end=a[9];
- if(number>end)
- a[10]=number;
- else
- {for(i=0;i<10;i++)
- {if(a[ i ]>number)
- {temp1=a[ i ];
- a[ i ]=number;
- for(j=i+1;j<11;j++)
- {temp2=a[j];
- a[j]=temp1;
- temp1=temp2;
- }
- break;
- }
- }
- }
- printf("Now array a:\n");
- for(i=0;i<11;i++)
- printf("%5d",a[ i ]);
- printf("\n");
- return 0;
- }
——谭浩强 ,《C程序设计(第四版)学习辅导》,清华大学出版社,2010年7月,p57~58
这个题目很简单,但代码却混乱无比,堪称混乱之集大成者。如果想学习怎样把代码写的混乱无比,从中可以品悟出很多独家秘诀。
秘诀一、无聊
- int end ;
- end=a[9];
- if(number>end)
- //……
这段代码堪称无聊之代表作。方法很简单,就是定义一个并不需要的变量(end),毫无意义地对它赋值(end=a[9]),再用这个克隆的变量(end)做“>”运算而不是用原来的数据对象(a[9])进行运算。而使用原来的数据对象做运算,除了可以提高程序效率、使得代码可读性更好之外,实在是一点也不够无聊啊。不无聊的代码写起来很容易很简单,通常酱紫地:
- if ( number > a[9] )
- //……
秘诀二、忽左忽右,前后不一
把一个数插入到一个有序的数组中,通常有两种考虑:或者从前往后先找到待插入数的位置再做打算,或者从后向前逐步调整。但这绝对达不到混乱的目的。样本代码中先是把数据放在了最后
貌似要从后向前,然而这只是一个虚招。紧接着又
- for(i=0;i<10;i++)
- {if(a[ i ]>number)
这又是前向后的招数了。
这里,制造混乱的要诀在于忽前忽后,忽左忽右,任何一个招数都不使老,任何一个思路都不贯彻始终,这样才能让人捉摸不透,制造混乱,之后方可在乱中取胜。
而寻常的招数则是无条件地先把待插入的数放在数组的最后,例如
然后再对数组元素的次序逐步调整以到达有序的状态。
或者,先从前面找到待插入数据的正确位置,例如
- int insert_pos ;
- scanf("%d",&number);
- for(insert_pos=0; insert_pos < 10 && number > a[insert_pos]; insert_pos++)
- ;
待找到应该插入的位置之后再做进一步的处理。
寻常的招数固然思路清晰且简洁易懂,然而主要的缺点就是达不到天下大乱之奇功。
秘诀三、颠三倒四,手忙脚乱
如果按照从前向后的思路,在找到待插入的位置后,首先考虑的应该是把这个位置上和以后位置上的数组元素向后移动,空出待插入元素的位置,然后插入:
- for( i = 11 – 1 ; i > insert_pos ; i--)
- a[i]=a[i-1];
- a[insert_pos]= number;
之后数组成为新的有序状态。然而,这种简单的做法实在是属于乱而无术。究竟怎样才能达到乱而有术的境界呢?样本代码给我们做出了极出色的示范。
首先,在找到待插入的位置后,并不等安排好其他数组元素的位置再插入,而是迫不及待,把数据插入进去
- {for(i=0;i<10;i++)
- {if(a[ i ]>number)
- {temp1=a[ i ];
- a[ i ]=number;
这样,temp1这样多余的变量就顺理成章地成了必不可少的变量,因为总不能把被排挤出的原来的a[i]给摔掉啊。紧接着
- for(j=i+1;j<11;j++)
- {temp2=a[j];
- a[j]=temp1;
- temp1=temp2;
- }
就如同马戏团小丑表演的抛球杂耍一样——不停地把球抛起(temp2=a[j];)、接住(a[j]=temp1;),同时忙里抽闲地还要不停地从一只手倒入另一只手中(temp1=temp2;),颠三倒四手忙脚乱得让人眼花缭乱目不暇接。这种把几件事搅和在一起忙活的方法实乃制造混乱秘笈中之秘笈。
忙完之后,发现寻找插入位置的循环竟然还没结束,于是,赶紧刹车——
仿佛马戏表演进入高潮之后戛然而止。幸好制动及时,没有照成追尾。后面再像没事人一样按平常的方式输出——大乱之后的大治。实在是乱出了风格乱出了水平,乱的让人高山仰止。相比之下,下面这种写法
- #include <stdio.h>
- int main( )
- {
- int a[11] = {1,4,6,9,13,15,19,18,40,100};
- int number , i , insert_pos ;
- printf("array a:\n");
- for( i = 0 ; i < 11 - 1 ;i++)
- printf("%d ",a[i]);
- putchar('\n');
- printf("insert data:");
- scanf("%d",&number);
- //寻找正确的插入位置
- for( insert_pos = 0 ;
- ( insert_pos < 11 -1 ) && (number > a[insert_pos]) ;
- insert_pos++ )
- ;
-
- //插入位置及后面的元素后移
- for( i = 11 - 1 ; i > insert_pos ; i-- )
- a[i]=a[i-1];
-
- //插入
- a[insert_pos]= number;
- //输出
- printf("Now array a:\n");
- for( i = 0 ; i < 11 ; i++ )
- printf("%d " , a[i] );
- putchar('\n');
-
- return 0;
- }
就显得太过于井井有条昆乱不挡了。貌似一副怎么也乱不起来的样子。更有甚者
- #include <stdio.h>
- int main( )
- {
- int a[11] = {1,4,6,9,13,15,19,18,40,100};
- int i ;
- printf("array a:\n");
- for( i = 0 ; i < 11 - 1 ;i++)
- printf("%d ",a[i]);
- putchar('\n');
- printf("insert data:");
- scanf("%d",&a[ 11 - 1 ] );
- for( i = 11 - 1 ; (i > 0) && ( a[i] < a[i-1] ) ; i-- )
- {
- int temp ;
- temp = a[ i ] ;
- a[ i ] = a[ i - 1] ;
- a[ i - 1 ] = temp ;
- }
- //输出
- printf("Now array a:\n");
- for( i = 0 ; i < 11 ; i++ )
- printf("%d " , a[i] );
- putchar('\n');
-
- return 0;
- }
则非但不忙不乱,简直称得上是有些游手好闲了。
阅读(1588) | 评论(0) | 转发(0) |