第5章 利用数组处理批量数据   5.1 用筛选法求100 之内的素数。 解 : 解题思路。所谓“筛法”指的是“埃拉托色尼(Eratosthenes)筛法”。埃拉托色尼 是古希腊的著名数学家。他采取的方法是,在一张纸上写上1~1000 的全部整数,然后逐 个判断它们是否是素数,找出一个非素数,就把它挖掉,最后剩下的就是素数,见图5. 1 。   ...................................... ① 23 ④ 5 ⑥ 7 ⑧ ⑨ ⑩ 11 .. .. 13 .. .... .. 19 .............. .. 29 ............ ........ .. 23 .. .. ...... .. 31 .. .. .. .. .. .. 17 .. 37 .................... .. .. .. .. .. .. 41 ...... .. 47 .. .. .. .. 43 ............ … 图 5. 1 具体做法如下。 (1) 先将 1 挖掉(因为 1 不是素数)。 (2) 用 2 去除它后面的各个数,把能被 2 整除的数挖掉,即把 2 的倍数挖掉。 (3) 用 3 去除它后面各数,把 3 的倍数挖掉。 (4) 分别用4,5…各数作为除数去除这些数以后的各数。这个过程一直进行到在除 数后面的数已全被挖掉为止。例如在图5. 1 中找1~50 的素数,要一直进行到除数为47 为止。事实上,可以简化,如果需要找1~ n 的素数表,只须进行到除数为 n ( 取其整数 ) 即可。例如对1~50,只须进行到将7(即50 的整数部分)作为除数即可。请读者思考为 什么 ? 上面的算法可表示如下。 (1) 挖去1。 (2) 用下一个未被挖去的数 p 去除 p 后面各数,把 p 的倍数挖掉。 (3) 检查 p 是否小于 n 的整数部分(如果n=1000,则检查p<31?) , 如果是,则返回 (2)继续执行,否则就结束。 (4) 剩下的数就是素数。 用计算机解此题,可以定义一个数组a。数组元素a[1 ] ~a[n ] 分别代表1~ n 这 n 个数。如果检查出数组 a 的某一元素的值是非素数,就使它变为0,最后剩下不为 0 的就 是素数。 编写程序如下。  43   #include #include          //程序中用到求平方根函数sqrt int main()  { int i,j,n,a[101];        / /定 义a 数组包含101 个元素  for (i=1;i<=100;i++)      // a [0]不用,只用a[1]~a[100]    a[i]=i;            //使a[1]~a[100] 的值为1~100  a[1]=0;              //先"挖掉"a[1]  for (i=2;i int main()  { int i,j,min,temp,a[11];  printf("enter data:\n");  for (i=1;i<=10;i++)  {printf("a[%d]=",i);   scanf("%d",&a[i]);    //输入10 个数  }  printf("\n");  printf("The orginal numbers:\n");  for (i=1;i<=10;i++)   printf("%5d",a[i]);    / /输 出 这 10 个数  printf("\n");  for (i=1;i<=9;i++)     / / 以 下 8 行是对10 个数排序   {min=i;   for (j=i+1;j<=10;j++)    if (a[min]>a[j]) min=j;   temp=a[i];         //以下3 行将a[i+1]~ a[10]中最小者与a[i]对换   a[i]=a[min];   a[min]=temp;   }  printf("\nThe sorted numbers :\ n ") ;    //输出已排好序的10 个数  for (i=1;i<=10;i++)   printf("%5d",a[i]);  printf("\n");  return 0; } 运行结果:   enter data: a[1]=1 ↙ a[2]=16 ↙ a[3]=5 ↙ a[4]=98 ↙ a[5]=23 ↙ a[6]=119 ↙ a[7]=18 ↙ a[8]=75 ↙ a[9]=65 ↙ a[10]=81 ↙ The orginal numbers:   1 16  5 98 23 119 18 75 65 81   45 The sorted numbers:   1  5 16 18 23 65 75 81 98 119  5.3 求一个3×3 的整型二维数组对角线元素之和。 解: 编写程序如下。   #include int main()  { int a[3][3],sum=0; int i,j;  printf("enter data:\n");  for (i=0;i<3;i++)   for (j=0;j<3;j++)     scanf("%d",&a[i][j]);  for (i=0;i<3;i++)   sum=sum+a[i][i];  printf("sum=%6d\n",sum);  return 0; } 运行结果:   enter data: 1 ↙ 2 ↙ 3 ↙ 4 ↙ 5 ↙ 6 ↙ 7 ↙ 8 ↙ 9 ↙ sum=  15 关于输入数据方式的讨论: 在程序的scanf 语句中用%d 作为输入格式控制,上面输入数据的方式显然是可行 的。其实也可以在一行中连续输入9 个数据,如:   1 2 3 4 5 6 7 8 9 ↙ 结果也一样。在输入9 个数据并按回车键后,这9 个数据被送到内存中的输入缓冲区中, 然后逐个送到各个数组元素中。下面的输入方式也是正确的:   1 2 3 ↙ 4 5 6 ↙ 7 8 9 ↙ 或者:  46   1 2 ↙ 3 4 5 6 ↙ 7 8 9 ↙ 都是可以的。 请考虑,如果将程序第7 ~ 9 行改为   for (j=0;j<3;j++)  scanf(" %d %d %d",&a[0][j],&a[1][j],&a[2][j]); 应如何输入? 是否必须一行输入3 个数据,如:   1 2 3 ↙ 4 5 6 ↙ 7 8 9 ↙ 答案是可以按此方式输入,也可以不按此方式输入,而采用前面介绍的方式输入,不论分 多少行、每行包括几个数据,只要求最后输入9 个数据即可。 程序中用的是整型数组,运行结果是正确的。如果用的是实型数组,只须将程序第4 行的int 改为float 或double 即可,并且在scanf 函数中使用%f 或%lf 格式声明。 5.4 已有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数 组中。 解: 解题思路。设数组a 有n 个元素,而且已按升序排列,在插入一个数时按下面的 方法处理: (1) 如果插入的数num 比a 数组最后一个数大,则将插入的数放在a 数组末尾。 (2) 如果插入的数num 不比a 数组最后一个数大,则将它依次和a[0] ~ a[n-1] 比 较,直到出现a[i] >num 为止,这时表示a[0] ~ a[i -1]各元素的值比num 小,a[i] ~ a[n-1] 各元素的值比num 大。num 理应插到a[i-1] 之后、a[i]之前。怎样才能实现此 目的呢? 将a[i]~ a[n-1] 各元素向后移一个位置(即a[i]变成a[i+1],…,a[n-1]变成 a[n])。然后将num 放在a[i]中。N.S 图见图5.3。 显示初始数组 输入待插入的数值num    num>末尾元素  T F  num 插在数 组尾 for (i = 0; i<10; i++)    a (i)>num  T F num 插在a(i)处 将原第i 个元素之后的 所有元素下标依次增1 输出结果 图 5.3  47   编写程序如下。   #include int main()  { int a[11]={1,4,6,9,13,16,19,28,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; } 运行结果:   array a:   1  4  6  9 13 16 19 28 40 100 insert data: 5 ↙ Now,array a:   1  4  5  6  9 13 16 19 28 40 100  48   5.5 将一个数组中的值按逆序重新存放。例如,原来顺序为8,6,5,4,1,要求改为 1,4,5,6,8。 解: 解题思路。以中间的元素为中心,将其两侧对称的元素的值互换。例如,将8 和 1 互换,将6 和4 互换。N.S 图见图5. 4。 显示初始数组元素 for (i = 0; i<N / 2; i++) 第i 个元素与第N-i-1 个元素互换 显示逆序存放的各数组元素 图 5. 4 编写程序如下。   #include #define N 5          //定义N 代表5 int main()  { int a[N],i,temp;  printf("enter array a:\n");  for (i=0;i #define N 10 int main()  { int i,j,a[N][N];           //数组为10 行10 列  for (i=0;i int main()  { int a[15][15],i,j,k,p,n;  p=1;  while(p= =1)   {printf("enter n(n=1 to 15):");    //要求阶数为1~15 的奇数   scanf("%d",&n);   if ((n!=0) && (n<=15) && (n%2!=0)) //检查n 是否为1~15 的奇数     p=0;   }  //初始化   for (i=1;i<=n;i++)   for (j=1;j<=n;j++)     a[i][j]=0;  //建立魔方阵   j=n/2+1;  a[1][j]=1;  for (k=2;k<=n.n;k++)   {i=i-1;   j=j+1;   if ((i<1) && (j>n))    {i=i+2;