zoukankan      html  css  js  c++  java
  • 混乱是怎样炼成的——《C解毒》试读

    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] )
    //……
    

    秘诀二、忽左忽右,前后不一

    把一个数插入到一个有序的数组中,通常有两种考虑:或者从前往后先找到待插入数的位置再做打算,或者从后向前逐步调整。但这绝对达不到混乱的目的。样本代码中先是把数据放在了最后

        a[10]=number;
    

    貌似要从后向前,然而这只是一个虚招。紧接着又

    for(i=0;i<10;i++)
           {if(a[ i ]>number)
    

    这又是前向后的招数了。

    这里,制造混乱的要诀在于忽前忽后,忽左忽右,任何一个招数都不使老,任何一个思路都不贯彻始终,这样才能让人捉摸不透,制造混乱,之后方可在乱中取胜。
    而寻常的招数则是无条件地先把待插入的数放在数组的最后,例如

    scanf("%d",&a[10]);
    

    然后再对数组元素的次序逐步调整以到达有序的状态。

    或者,先从前面找到待插入数据的正确位置,例如

    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;),颠三倒四手忙脚乱得让人眼花缭乱目不暇接。这种把几件事搅和在一起忙活的方法实乃制造混乱秘笈中之秘笈。

    忙完之后,发现寻找插入位置的循环竟然还没结束,于是,赶紧刹车——

              break;    
    

    仿佛马戏表演进入高潮之后戛然而止。幸好制动及时,没有照成追尾。后面再像没事人一样按平常的方式输出——大乱之后的大治。实在是乱出了风格乱出了水平,乱的让人高山仰止。相比之下,下面这种写法

    #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');

    return0;
    }

    就显得太过于井井有条昆乱不挡了。貌似一副怎么也乱不起来的样子。更有甚者

    #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');

    return0;
    }

    则非但不忙不乱,简直称得上是有些游手好闲了。

  • 相关阅读:
    react路由组件&&非路由组件
    react函数式组件(非路由组件)实现路由跳转
    react使用antd组件递归实现左侧菜单导航树
    【LeetCode】65. Valid Number
    【LeetCode】66. Plus One (2 solutions)
    【LeetCode】68. Text Justification
    【LeetCode】69. Sqrt(x) (2 solutions)
    【LeetCode】72. Edit Distance
    【LeetCode】73. Set Matrix Zeroes (2 solutions)
    【LeetCode】76. Minimum Window Substring
  • 原文地址:https://www.cnblogs.com/pmer/p/2130032.html
Copyright © 2011-2022 走看看