利用数组处理批量数据   1.用筛选法求100之内的素数。   【解】 所谓“筛选法”指的是“埃拉托色尼(Eratosthenes)筛选法”。他是古希腊的著名数学家。他采取的方法是:在一张纸上写上1~1000的全部整数,然后逐个判断它们是否为素数,找出一个非素数,就把它挖掉,最后剩下的就是素数,见图5.1。 图 5.1   具体做法如下:   (1)先将1挖掉(因为1不是素数)。   (2)用2去除它后面的各个数,把能被2整除的数挖掉,即把2的倍数挖掉。   (3)用3去除它后面各数,把3的倍数挖掉。   (4)分别用4,5…各数作为除数去除这些数以后的各数。这个过程一直进行到除数后面的数已全被挖掉为止。例如在图5.1中找1~50的素数,要一直进行到除数为47为止(事实上,可以简化,如果需要找1~n的素数表,只须进行到除数为(取其整数)即可。例如对1~50,只须进行到将7()作为除数即可。请读者思考为什么)。   上面的算法可表示为:   (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的就是素数。   程序如下: #include #include using namespace std; #include 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 using namespace std; int main( ) {int i,j,min,temp,a[11]; cout << "enter data:" << endl; for (i=1;i<=10;i++) {cout << "a[" << i << "]="; cin >> a[i]; //输入10个数 } cout << endl << "The original numbers:" << endl; for (i=1;i<=10;i++) cout << a[i] << " "; //输出这10个数 cout << endl; 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; } cout << endl << "The sorted numbers:" << endl; for (i=1;i<=10;i++) //输出已排好序的10个数 cout << a[i] << " "; cout << endl; return 0; }   运行结果: enter data: a[1]=36 ↙ a[2]=?– 9↙ a[3]=5↙ a[4]=6↙ a[5]=?–1↙ a[6]=35↙ a[7]=34↙ a[8]=738↙ a[9]=18↙ a[10]=11↙ The original numbers: 36 –9 5 6 –1 35 34 738 18 11 The sorted numbers: –9 –1 5 6 11 18 34 35 36 738   说明:定义a数组有11个元素,即a[0]~a[10],但实际上只对a[1]~a[10]这10个元素输入值并排序。a[0]未用到,这样符合人们的习惯。   3.求一个3×3矩阵对角线元素之和。   【解】 #include using namespace std; int main( ) {int a[3][3],sum=0; int i,j; cout << "enter data:" << endl; for (i=0;i<3;i++) for (j=0;j<3;j++) cin >> a[i][j]; for (i=0;i<3;i++) sum=sum+a[i][i]; cout << "sum=" << sum << endl; return 0; }   运行结果: enter ata: 1 3 5 7 9 11 13 15 17↙ sum=27   此程序中用的是整型数组,运行结果是正确的。如果用的是实型数组,只须将程序第4行的int改为float或double即可,在输入数据时可输入单精度或双精度的数。   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]中。   按此思路编写程序如下: #include using namespace std; int main( ) {int a[11]={ 1 6 13 17 28 40 56 78 89 100}; int num,i,j; cout << "array a:" << endl; for (i=0;i<10;i++) cout << a[i] << " "; cout << endl; cout << "insert data:"; cin >> num; if (num>a[9]) a[10]=num; else {for (i=0;i<10;i++) {if (a[i]>num) {for (j=9;j>=i;j– –) a[j+1]=a[j]; a[i]=num; break; } } } cout << "Now, array a:" << endl; for (i=0;i<11;i++) cout << a[i] << " "; cout << endl; return 0; }   运行结果: array a: 1 6 13 17 28 40 56 78 89 100 insert data:15↙ Now,array a: 1 6 13 15 17 28 40 56 78 89 100   5.将一个数组中的值按逆序重新存放。例如,原来顺序为8,6,5,4,1。要求改为1,4,5,6,8。   【解】 解此题的思路是:以中间的元素为中心,将其两侧对称的元素的值互换即可。例如将8和1互换,将6和4互换。程序如下: #include using namespace std; int main( ) { const int n=5; int a[n],i,temp; cout << "enter array a:" << endl; for (i=0;i> a[i]; cout << "array a:" << endl; for (i=0;i #include using namespace std; int main( ) {const int n=11; int i,j,a[n][n]; //数组为11行11列, 0行0列不用 for (i=1;i using namespace std; int main( ) { const int n=4,m=5; //假设数组为4行5列 int i,j,a[n][m],max,maxj; bool flag; for (i=0;i> a[i][j]; for (i=0;imax) {max=a[i][j]; //将本行的最大数存放在max中 maxj=j; //将最大数所在的列号存放在maxj中 } flag=true; //先假设是鞍点, 用flag为真来代表 for (int k=0;ka[k][maxj]) //将最大数和其同列元素相比 {flag=false; //如果max不是同列最小, 表示不是鞍点, 令flag为假 continue;} if(flag) //如果flag为真, 表示是鞍点 {cout << "a[" << i << "][" << "[" << maxj << "]=" << max << endl; //输出鞍点的值和所在行列号 break; } } if(!flag) //如果flag为假表示鞍点不存在 cout << "It does not exist!" << endl; return 0; }   运行结果: ① 1 2 3 4 5↙ (输入4行5列数据) 2 4 6 8 10↙ 3 6 9 12 15↙ 4 8 12 16 20↙ a[0][4]=5 (0行4列元素是鞍点, 其值为5) ② 1 12 3 4 5↙ (输入4行5列数据) 2 4 16 8 10↙ 3 6 9 12 15↙ 4 8 12 16 20↙ It does not exist! (无鞍点)   8.有15个数按由大到小的顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则打印出“无此数”。   【解】 从一维数组中查一个数最简单的方法是从第1个数开始顺序查找,将要找的数与数组中的数一一比较,直到找到为止(如果数组中无此数,则应找到最后一个数,然后判定“找不到”)。   但这种“顺序查找法” 效率低,如果表列中有1000个数,且要找的数恰恰是第1000个数,则要进行999次比较才能得到结果。平均比较次数为500次。   折半查找法是效率较高的一种方法。基本思路如下:   假如有已按由小到大排好序的9个数,a[1]~a[9],其值分别为 1,3,5,7,9,11,13,15,17   若想查3是否在此数组中,可以先找出表列中居中的数,即a[5],将要找的数3与a[5]比较,a[5]的值是9,发现a[5]>3,显然3应当在a[1]~a[5],而不会在a[6]~a[9]。这样就可以缩小查找范围,甩掉a[6]~a[9]这一部分,即将查找范围缩小为一半。再找a[1]~a[5]的居中的数,即a[3],将要找的数3与a[3]比较,a[3]的值是5,发现a[3]>3,显然3应当在a[1]~a[3]。这样又将查找范围缩小一半。再将3与a[1]~a[3]的居中的数a[2]比较,发现要找的数3等于a[2],查找结束。一共比较了3次。如果表列中有n个数,则最多比较的次数为 int(log2n)+1。   程序如下: #include using namespace std; int main( ) { const int n=7; int i,number,top,bott,mid,loca,a[n]; bool flag=true,sign; char c; cout << "enter data:" << endl; cin >> a[0]; i=1; while(i> a[i]; if (a[i]>=a[i–1]) i++; else cout << "enter this data again:"; } cout << endl; for (i=0;i> number; sign=false; //sign为假表示尚未找到 top=0; //top是查找区间的起始位置 bott=n–1; //bott是查找区间的最末位置 if ((numbera[n–1])) //要查的数不在查找区间内 loca = –1; //表示要查找的数不在正常范围内 while ((!sign) && (top<=bott)) {mid=(bott+top)/2; //找出中间元素的下标 if (number==a[mid]) //如果要查找的数正好等于中间元素 {loca=mid; //记下该下标 cout << "Find " << number << ", its position is " << loca+1 << endl; //由于下标从0算起, 而人们习惯从1算起, 因此输出数的位置时要加1 sign=true; //表示找到了 } else if (number> c; if (c=='N' || c=='n') flag=false; //flag为开关变量, 控制程序是否结束运行 } return 0; }   运行结果: enter data: (输入数据) 6 8 12 10↙ (数据未按由小到大顺序输入) enter this data again: (要求重新输入) 23 34 44 45 56 57 58↙