第七章 数组
7.1
例7-1
输出所有大于平均数的数。输入n个整数(1≤n≤10),计算这些数的平均值,在输出所有大于平均值的数。
#include <stdio.h>
int main(void){
int i,n;
double average,sum;
int a[10];
printf("Enter:");
scanf("%d",&n);
if(n>=1 && n<=10){
printf("Enter %d integers:",n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
sum=0;
for(i=0;i<n;i++){
sum=sum+a[i];
}
average=sum/n;
printf("average=%.2f\n",average);
printf(">average:");
for(i=0;i<n;i++){
if(a[i]>average){
printf("%d ",a[i]);
}
}
printf("\n");
}else{
printf("Invaild Value.\n");
}
return 0;
}
程序中定义一个整数型数组a后,在内存中开辟了10个连续的单元,用于存放数组a的是个元素a[0]~a[9]的值,这些元素类型都是整型,相应的内存单元的存储内容即是例题中输入的十个数对应的位置。
在程序中使用数组,可以让一批相同类型的变量使用同一个数组变量名,用下标来相互区分,优美简洁,可读性好,便于使用循环结构。
7.1.2 一维数组的定义和引用
定义一个数组需要明确数组变量名,数组元素的类型和数组的大小(数组中的元素数量)。
一维数组的定义方式一般为:
类型名 数组名[数组长度];
数组名指定数组中每个元素的类型;数组名是数组变量的名称,是一个合法的标识符
例如:int a[10]; 就是定义一个有10个整数元素的数组a(数组长度是一个常量)
数组名是一个地址常量,存放数组内存空间的首地址
...
7.1.3 一维数组的初始化
和简单变量的初始化一样,在定义数组时,也可以对数组元素赋初始值,一般形式为:
类型名 数组名[数组长度]={数值表};
例如:
int a[10]={0,1,2,3,4,5,6,7,8,9};
定义数组a,则a[0]为0,a[1]为1...
虽然C语言规定,只有静态储存的数组才能初始化,但是一般的C编译系统都允许对动态存储的数组赋初值。静态数组例如:
static int b[5]={1,2,3,4,5};
初始化静态数组b。静态存储的数组如果没有初始化,系统将自动给所有的数组元素赋0(不同编译器不同)
数组的初始化也可以针对部分元素,例如:
static int b[5]={1,2,3};
支队数组b的前3个元素赋初值,其余的元素的初值都为0
数组初始化时,如果对全部元素都赋了初值,就可以省略数组长度,例如:
int a[ ]={1,2,3,4,5,6,7,8,9,10};
此时系统会根据初值的个数自动给出数组的长度
显然,如果只对部分元素初始化,数组长度时不能省略的。为了改善程序的可读性,尽量避免出错,不管是否对全部数组元素赋初值,都不省略数组长度。
7.1.4 使用一维数组编程
1. 选择排序法
练(原书中例7-5):输入一个正整数n(1<n≤10),再输入n个整数,用选择法将它们从小到大排列后输出
- 第1步:在未排序的n个数(a[0]~a[n-1])中找到最小值,将它的值于a[0]的值交换;
- 第2步:在剩下未排序的n-1个数(a[1]~a[n-1])中找到最小数,将它与a[1]的值交换;
- ......
- 第n-1步:在剩下未排序的两个数(a[n-2]和a[n-1])中找到最小数,将它与a[n-2]的值交换。
编写程序:
#include <stdio.h>
#define MAXN 10
int main(void){
int a[MAXN],n,i,k,index,temp;
scanf("%d",&n);
for(i=0;i<=n-1;i++){
scanf("%d",&a[i]);
}
for(k=0;k<=n-1;k++){ //选n次
index=k;
for(i=k+1;i<=n-1;i++){ //比较时的每一次
if(a[index]>a[i]){
index=i;
}
}
temp=a[k];
a[k]=a[index];
a[index]=temp;
}
for(i=0;i<=n-1;i++){
printf("%d ",a[i]);
}
return 0;
}
练(原书中例7-6):调查电视节目受欢迎程度。某电视台要调查观众对该台8个栏目的受欢迎情况,共调查了n(1≤n≤1000)位观众。现要求编写程序,输入每一位观众的投票情况(每位观众只能选择一个喜欢的栏目投票),统计输出各栏目的得票情况。
#include <stdio.h>
#define MAXN 8
int main(void){
int i,n,respond;
int count[MAXN+1]={0,0,0,0,0,0,0,0};
printf("人数n=");
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&respond);
if(respond>=1 && respond<=8){
count[respond]++;
}
}
for(i=1;i<=MAXN;i++){
printf("%4d %4d\n",i,count[i]);
}
return 0;
}
2. 二分查找法(重点)
练(原书中例7-7):设已有一个n(1≤n≤10)个元素的整型数组a,且按值从小到大有序排列。输入一个整数x,然后再数组中查找x,如果找到,输出相应的下标,否则,输出"Not found"。
查找和排序一样,都是程序设计的最基本的算法。对数组元素从头到尾进行遍历,一旦数组元素量很大,其查找的效率就不高。二分查找是查找效率较高的一种,但前提是数组元素必须有序的,算法思路如下:
设n个元素的数组a已有序(假定a[0]到a[n-1]升序排列),用low和high两个变量来表示查找区间的端点元素的下标,即在a[low]~a[high]间去查找x。初始状态为low=0,high=n-1。首先要用查找的x与查找区间中间的中间位置元素a[mid](mid=(low+high)/2)比较,如果相等则找到,算法终止;如果x<a[mid],由于数组是升序排列的,则只要在a[low]~a[mid-1]内查找;如果x>a[mid],则只要继续在a[mid+1]~a[high]区间继续查找。也就是根据与中间元素比较的情况产生了新的区间端点元素下标值low、high,当出现low>high时算法终止,即不存在值为x的元素。
#include <stdio.h>
int main(void){
int a[10]={1,2,3,4,5,6,7,8,9,10};
int low,high,mid,i,n=10,x,index;
printf("x=");
scanf("%d",&x);
low=0;
high=n-1;
while(low<=high){
mid=(low+high)/2;
if(a[mid]==x){
index=mid;
break;
}else if(x>a[mid]){
low=mid+1;
}else{
high=mid-1;
}
}
if(low<=high){
printf("Index:%d",index);
}else{
printf("Not found");
}
return 0;
}
练习7-2
求最大值及下标。输入一个正整数n(1<n≤10),再输入n个整数,输出最大值及其对应的最小下标,下标从0开始。
#include <stdio.h>
int main(void){
int i,k,n,index,temp;
int a[n-1];
printf("n=");
scanf("%d",&n);
printf("Enter %d data:",n);
for(i=0;i<=n-1;i++){
scanf("%d",&a[i]);
}
for(k=0;k<=n-1;k++){ //循环n次
index=k; //将最小的数组底数赋值为k
for(i=k+1;i<=n-1;i++){ //每一次循环中将其与下面的数进行比对
if(a[index]<a[i]){
index=i; //每一次比对将最小的数的底数赋给index
}
}
/* 将a[k]与a[index]的值交换 */
temp=a[k];
a[k]=a[index];
a[index]=temp;
}
for(i=0;i<=n-1;i++){
printf("%4d%4d\n",i,a[i]);
}
return 0;
}
练习7-3
将数组中的数逆序存放。输入一个正整数n(1<n≤100),再输入n个整数,存入数组a中,先将数组a中的这n个数逆序存放,再按顺序输出数组a中的n个元素。
#include <stdio.h>
int main(void){
int i,k,n,index,temp;
printf("Enter n:");
scanf("%d",&n);
int a[n];
printf("Enter data:");
for(i=0;i<=n-1;i++){
scanf("%d",&a[i]);
}
for(k=0;k<=n-1;k++){
index=k;
for(i=k+1;i<=n-1;i++){
if(a[i]<a[index]){
index=i;
}
}
temp=a[k];
a[k]=a[index];
a[index]=temp;
}
for(i=0;i<=n-1;i++){
printf("%d ",a[i]);
}
return 0;
}
练习7-4
找出不是两个数组共有的元素。输入一个正整数n(1<n≤10),再输入n个整数,存入一个数组中;然后输入一个正整数m(1<m≤10),再输入m个整数,存入第二个数组中,找出所有不是这两个数组共有的元素。
#include <stdio.h>
int main(void){
int i,j,m,n,k=0;
/*定义两个数组*/
printf("Enter n:");
scanf("%d",&n);
int a[n];
printf("Enter data:");
for(i=0;i<=n-1;i++){
scanf("%d",&a[i]);
}
printf("Enter m:");
scanf("%d",&m);
int b[m];
printf("Enter data:");
for(i=0;i<=m-1;i++){
scanf("%d",&b[i]);
}
for(i=0;i<=n-1;i++){ //将数组a与数组b比较,输出数组a与数组b的不同数
for(j=0;j<=m-1;j++){
if(a[i]==b[j]){ //当遇到相同的就跳出循环
break;
}
}
if(j==m){ //由于循环结构没被break时会使j=m,所以就可以认定此数为不相同的数
printf("%d ",a[i]);
}
}
/*同理输出数组b中的不同数*/
for(i=0;i<=m-1;i++){
for(j=0;j<=n-1;j++){
if(b[i]==a[j]){
break;
}
}
if(j==n){
printf("%d ",b[i]);
}
}
return 0;
}
7.2
7.2.2 二维数组的定义和引用
C语言支持多维数组,最常见的多维数组为二维数组,主要用于二维表和矩阵
1. 定义
二位数组的定义形式为:
类型名 数组名[行长度][列长度];
类型名指定数组中的每个元素的类型,数组名是数组变量的名称,是一个合法的识别符,行长度和列长度是整数常量表达式,分别给定数组的行数和列数。
如定义一个二位数组a,3行2列,一共6个元素:
int a[3][2];
2. 引用
引用二位数组的元素要指定两个下标,即行下标和列下标,形式为:
数组名[行下标][列下标];
二维数组在内存中的存放形式 :
7.2.3 二维数组的初始化
在定义二维数组时,也可以对数组元素赋初值,二维数组的初始化方法有两种:
1.分行赋初值
类型名 数组名[行长度][列长度]={{初值表0},{初值表1},...{初值表n}};
例如:
int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
此时,a数组的各元素为:
2.顺序赋初值
类型名 数组名[行长度][列长度]={初值表};
根据数组元素在内存中的存放顺序,会把初值表中的数据依次赋给元素
例如:
int a[3][3]={1,2,3,4,5,6,7,8,9};
等价于
int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
二维数组初始化时,如果对全部元素都赋了初值,或分行赋初值时,在初值表中列出了全部行,就可以忽略行的长度,但是不建议这样做
7.2.4 使用二维数组编程
矩阵的术语与二维数组下标的对应关系:
例7-9
方阵转置。输入一个正整数n(1<n≤6),根据下式生成一个n × n的方阵,将该方阵转置(行列互换)后输出。
#include <stdio.h>
#define MAXN 6
int main(void){
int i,j,n,temp;
int a[MAXN][MAXN];
printf("Enter n:");
scanf("%d",&n);
for(i=0;i<n;i++){
for(j=0;j<n;j++){
a[i][j]=i*n+j+1;
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(i<=j){
temp=a[i][j];
a[i][j]=a[j][i];
a[j][i]=temp;
}
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf("%4d",a[i][j]);
}
printf("\n");
}
return 0;
}
练习7-7
矩阵计算。读入一个正整数n(1≤n≤6),再读入n阶方阵a,计算该矩阵除副对角线、最后一列和最后一行以外的所有元素之和。副对角线为从矩阵的右上角至左下角的连线。
#include <stdio.h>
#define MAXN 6
int main(void){
int i,j,n,sum=0;
int a[MAXN][MAXN];
printf("Enter n:");
scanf("%d",&n);
for(i=0;i<=n-1;i++){
for(j=0;j<=n-1;j++){
a[i][j]=i*n+j+1;
}
}
for(i=0;i<=n-1;i++){
for(j=0;j<=n-1;j++){
if(i+j!=n-1&&i!=n-1&&j!=n-1){
sum+=a[i][j];
}
}
}
printf("%d",sum);
return 0;
}
- 先写到这里,下次笔记补上数组部分 🙄 -