第6章 数 组.docx
- 文档编号:16352366
- 上传时间:2023-07-12
- 格式:DOCX
- 页数:63
- 大小:57.61KB
第6章 数 组.docx
《第6章 数 组.docx》由会员分享,可在线阅读,更多相关《第6章 数 组.docx(63页珍藏版)》请在冰点文库上搜索。
第6章数组
第六章数组
前面几章介绍的数据类型有整型、实型和字符型,它们都属于基本数据类型。
除此之外,C语言还提供了一些更为复杂的数据类型,称为构造类型或导出类型,它们由基本类型按一定的规则组合而成。
数组是最基本的构造类型,它是一组相同类型数据的有序集合。
数组中的元素在内存中连续存放,每个元素都属于同一种数据类型,用数组名和下标可以唯一确定数组元素。
下面我们先看看下面的一个例子,了解一下怎样用数组。
小小示例:
#include
main()
{inti,a[10];
for(i=0;i<10;i++)
scanf("%d",&a[i]);
//a[i]=i;
for(i=9;i>=0;i--)
printf("%d",a[i]);
printf("\n");
return0;
}
从键盘上(程序)往数组(a)里连续送入的数据是:
0123456789
程序将数组(a)里的数据逆序连续输出的是:
9876543210
6.1.1程序解析
例6.1投票情况统计:
调查电视节目受欢迎程度。
某电视台要调查观众对该台8个节目(设相应栏目编号为1--8)的欢迎情况,共调查了1000名观众,现要编写程序,输入每一位观众的投票情况(每位观众只能选择一个最喜欢的栏目投票),统计输出各栏目的得票情况。
这是一个分类统计的问题,要累积并保存各栏目的得票数,按本章以前的方法需设置8个变量,这显然不是最好的办法。
因此我们用数组来解决。
#include
intmain(void)
{intcount[9];//设立数组,栏目编号从1-8,但数组一定要多设一个
inti,response;//定义变量,response(响应、反映、回答)
for(i=1;i<=8;i++)
count[i]=0;//各栏目计票数,事先要充0
for(i=1;i<=10;i++)//假设10个人投票
{printf("输入你选的栏目编号:
");
scanf("%d",&response);
if(response<1||response>8)
printf("这是一张废票:
%d\n",response);
else
count[response]++;//对应的栏目得票数加1
}
printf("结果result:
\n");
for(i=1;i<=8;i++)
printf("%4d%4d\n",i,count[i]);
intindex=1;//假设a[1]是最大值,即下标为1的元素最大
for(i=1;i<=8;i++)
if(count[i]>count[index])//如果a[i]比假设的最大值还大
index=i;//再假设a[i]是新的最大值,即下标为i的元素最大
printf("%d号栏目票数最多(%d票)!
\t祝贺%d号栏目当选\n",
index,count[index],index);
return0;
}
程序中用一个整形数组count,而不是用若干个整形变量来存放输入的数据。
程序中定义了一个整型数组count后,在内存中开辟了9个连续的单元,分别为元素count[0]~count[8]共9个元素,这些元素的类型都是整型。
由数组名count和下标唯一地确定每个元素。
本例中,栏目的编号被设计为与数组下标一致,即编号为i的栏目其得票数存放于count[i]单元,这样,当某一观众投票为k时,只需要做count[k]++即可,故count[0]在本例中不使用,这8个数组元素相应内存单元的存储如下:
存得票数
…
…
…
…
…
…
存得票数
count[0]count[1]……………………………………………..count[7]count[8]
在程序中使用数组,可以让一批相同类型的变量使用同一个数组变量名,用下标来相互区分。
它的优点是表达简洁,可读性好,便于使用循环。
6.1.2一维数组的定义和引用
1、定义
定义一个数组,需要明确数组变量名、数组元素的类型和数组的大小(即数组中元素的数量)
一维数组定义的一般形式为:
类型名数组名[数组长度];
类型名指定数组中每个元素的类型;数组名是数组变量的名称,是一个合法的标识符;数组长度是一个整型常量表达式,给定数组的大小。
例如:
inta[10];//定义一个有10个整型元素的数组a
charc[200];//定义一个有200个字符型元素的数组c
folatf[5];//定义一个有5个单精度浮点型元素的数组f
注意:
数组长度是一个常量
数组是一些具有相同类型数据的集合,数组中的数据按照一定的顺序排列存放。
同一数组中的每个元素都具有相同的数据类型,有统一的标识符,用不同的序号即下标来区分数组中的各元素。
在定义数组之后,系统根据数组中元素的类型及个数在内存中分配了一段连续的存储单元用于存放数组中的元素,并对这些元素进行连续编号,即下标,以区分不同的单元。
每个单元所需的字节数由数组定义时给定的类型来确定。
假设int类型占用2个字节,前面定义的数组a的起始地址是4010,则其内存分配形式如下图所示,每一个元素需2个字节,共20个字节。
由图可以看出,只要知道了数组第一个元素的地址以及每个元素所需的字节数,其余各个元素的内存地址均可计算得到。
C语言规定,数组名表示该数组所分配连续内存空间中第一个单元的地址,即首地址,由于数组空间一经分配之后在运动过程中不会改变,因此数组名是一个地址常量,不允许修改。
注意:
数组名是一个地址常量,存放数组内存空间的首地址。
0123456789下标
内存4010401240144016401840204022402440264028
地址
2、引用
定义数组后,就可以使用它了。
C语言规定,只能引用单个的数组元素,而不能一次引用整个数组。
数组元素的引用要指定下标,形式为:
数组名[下标]
下标可以是整型表达式。
它的合理取值范围是[0,数组长度-1],前面定义的数组a就有10个元素[0]、a[1]、……、a[9],注意不能使用a[10]。
这些数组元素在内存中按下标递增的顺序连续存储(如图6.1所示)。
注意:
数组下标不能越界。
数组元素的使用方法与同类型的变量完全相同。
例如:
intk,a[10];
定义了整型变量k和整型数组a。
在可以使用整型变量的任何地方,都可以使用整型数组a的元素。
例如:
k=3;
a[0]=23;
a[k-2]=a[0]+1;
scanf(“%d”,&a[9]);
都是合法的C语言语句。
请注意区分数组的定义和数组元素的引用,两者都要用到“数组名[整型表达式]”。
定义数组时,方括号内是常量表达式,代表数组长度,它可以包括整型常量和符号常量,但不能包含变量。
也就是说,数组的长度在定义时必须指定,在程序的运行过程中是不能改变的。
而表示数组元素时,方括号内是表达式,代表下标,可以是变量,下标的合理取值范围是[0,数组长度-1]。
C语言的语法不检查下标是否越界,在编程时,注意不要让下标越界。
因为,一旦发生下标越界,就会把数据写到其他变量所占的存储单元中,甚至写入程序段,有可能造成不可预料的运行结果。
6.1.3一维数组的初始化
和简单变量的初始化一样,在定义数组时,也可以对数组元素赋初值。
其一般形式为:
类型名数组[数组长度]=[处置表];
初值表中依次放着数组元素的初值。
例如:
inta[10]={1,2,3,4,5,6,7,8,9,10};
定义数组a并对数组元素赋初值,此时,a[0]为1,a[1]为2,……,a[9]为10。
虽然C语言规定只能静态存储的数组才能初始化,但一般的C编译系统都允许对动态存储的数组赋初值。
本教案中也允许对静态数组和动态数组初始化。
例如:
staticintb[5]={1,2,3,4,5};
初始化静态数组b。
静态存储的数组如果没有初始化,系统自动给所有的数组元素赋0.即:
staticintb[5];等价于staticintb[5]={0,0,0,0,0};
注意:
加“static(静态)”表示后面定义的变量是永久性的,如果不加(动态)就是局部性的。
数组的初始化也可以只针对部分元素,例如:
staticintb[5]={1,2,3};
只对数组b的前3个元素赋初值,其余元素的初值为0。
即b[0]为1,b[1]为2,b[2]为3,b[3]和b[4]都为0。
又如:
intfib[20]={0,1};对数组fib的前2个元素赋初值,其余元素的值不确定。
数组初始化时,如果对全部元素都赋了初值,就可以省略数组长度,例如:
inta[]={1,2,3,4,5,6,7,8,9,10};
此时,系统会根据初值的个数自动给出数组的长度。
即上述初始化语句等价于:
inta[10]={1,2,3,4,5,6,7,8,9,10};
显然,如果只对部分元素初始化,数组长度是不能省略的。
为了改善程序的可读性,尽量避免出错,建议在定义数组时,不管是否对全部数组元素赋初值,都不要省略数组长度。
6.1.4使用一维数组编程
数组的应用离不开循环。
将数组的下标作为循环变量,通过循环,就可以对数组的所有元素逐个进行处理。
例6.2利用数组计算菲波那契数列的前10个数,即1,1,2,3,5,8,13,…,55并
按每行打印5个数的格式输出。
斐波那契数是:
除前2项之外,后面1项总是前
2项之和。
用数组计算并存放菲波那契数的前10个数,有下列关系成立:
f[0]=f[1]=1;
f[n]=f[n-1]+f[n-2](2<=n<=9)
#include
main()
{inti;
intfib[20]={1,1};//数组初始化,生成菲波那契数列前两个数
//计算菲波那契数列剩余的8个数
for(i=2;i<10;i++)
fib[i]=fib[i-1]+fib[i-2];
//输出斐波那契数列
for(i=0;i<10;i++)//数组的下标10作为循环变量
{
printf("%d",fib[i]);
if((i+1)%10==0)//每输出10个数就换行
printf("\n");
}
return0;
}
输出结果:
11235813213455
例6.3顺序查找法,输入5个整数,将它们存入数组a中,再输入1个数x,然后在数组中查找x,如果找到,输出相应的下标,否则输出“NotFound”。
#include
intmain()
{inti,flag,x,a[5];
printf("输入5个整数:
\n");
for(i=0;i<5;i++)
scanf("%d",&a[i]);
printf("输入一个数:
");
scanf("%d",&x);
flag=0;//先假设x不在数组a中,置flag为0
for(i=0;i<5;i++)
if(a[i]==x)
{printf("在数组中找到了与x相等的数,相应的下标是:
%d即a[%d]\n",i,i);
flag=1;
break;
}
if(flag==0)
printf("NotFound数组中没有找到与x相等的数:
\n");
return0;
}
例6.4输入一个正整数n(1 (1)输出最小值和它所对应的下标 (2)将最小值与第一个数交换,输出交换后的n个数 #include intmain() {inti,index,n,temp,a[10];//index中文是索引、下标 printf("输入一个正整数n: "); scanf("%d",&n); printf("再输入%d个正整数: ",n); for(i=0;i scanf("%d",&a[i]); index=0;//假设a[0]是最小值,即下标为0的元素最小 for(i=1;i if(a[i] index=i;//再假设a[i]是新的最小值,即下标为i的元素最小 printf("最小值是: %d\t其下标值是: %d\n",a[index],index); temp=a[index]; a[index]=a[0]; a[0]=temp; for(i=0;i printf("%d",a[i]); printf("\n"); return0; } 例6.5用选择法对10个整数排序(从小到大) 设有数组a[11]有10个元素a[1]~a[10],将a[1]与a[2]~a[10]比较,若a[1]比a[2]~a[10]都小,则不进行交换,即无任何操作。 若a[2]~a[10]中有一个以上比a[1]小,则将其中最小的一个(假设为a[i])与a[1]交换,此时a[1]中存放了10个数中最小的那个数。 第二轮将a[2]与a[3]~a[10]比较,将剩下的9个数中的最小者a[i]与a[2]对换,此时a[2]中存放的是10个数中第2小的数。 以此类推,共进行9轮比较,a[1]到a[10]就按由小到大顺序存放了。 #include main() {inti,j,min,temp;//定义变量 inta[11];//定义数组,数组中存放10个数(元素),从a[1]~a[10]存放,但定 //时要定义a[11],而不是a[10],因为数组最后的一个元素位置系统自动//给放一个结束标志,所以定义数组时,一般都要多定义一个数组单元。 printf("Enterdata: \n"); for(i=1;i<=10;i++) {printf("a[%d]=",i); scanf("%d",&a[i]);//输入10个数 } printf("\n"); printf("你输入的10个数是: "); for(i=1;i<=10;i++) printf("%5d",a[i]);//输出你敲入的这10个数 printf("\n"); for(i=1;i<=9;i++)//以下8行是对10个数进行排序,i<=9是循环9次 {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("排好序的10个数是: "); for(i=1;i<=10;i++)//输出已排好序的10个数 printf("%5d",a[i]); printf("\n\n"); return0; } 运行结果是: Enterdata: a[1]=(敲入)6 a[2]=(敲入)90 a[3]=(敲入)45 a[4]=(敲入)56 a[5]=(敲入)5 a[6]=(敲入)15 a[7]=(敲入)44 a[8]=(敲入)78 a[9]=(敲入)58 a[10]=(敲入)99 你输入的10个数是: 690455651544785899 排好序的10个数是: 561544455658789099 程序的功能很明显,输入一批整数并排序,然后输出排好序后的数。 这就要求保存输入数据,并对它们进行处理,程序中用一个整型数组,而不是若干个整型变量来存放它们。 定义一个整型数组a后,在内存中开辟了10个连续的单元,用于存放数组a的10元素a[0]~a[9]的值,这些元素的类型都是整型,由数组名a和下标唯一地确定每个元素。 这10个数组元素接收输入数据后,相应内存单元的存储内容如图6.1所示。 程序中为适应人们的习惯,将0单元当做1单元开始。 内存地址4010401240144016401840204022402440264028 6 90 45 56 5 15 44 78 58 99 a a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9] 图6.1数组元素的存储 在程序中使用数组,可以让一批相同类型的变量使用同一个数组变量名,用下标来相互区分。 它的优点是表达简洁,可读性好,便于使用循环结构。 例6.6: 二分查找法。 设已有一个包含10个元素的整形数组a,且按值从小到大有序。 输入一个整数x,然后在数组中查找x,如果找到,输出相应的下标,否则输出“NotFound”。 查找和排序一样,都是程序设计的最基本算法。 例6.3是查找算法中最简单的一种,之所以称之为顺序查找,是因为其查找过程就是对数组元素从头到尾的遍历过程。 但是一旦数组元素很大,其查找的效率不高。 二分查找是查找效率较高的一种,但前提是数组元素必须是有序的,算法思路是: 设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)比较,如果相等则找到,算法终止;如果xa[mid],则只要在mid+1~high区间继续查找。 也就是根据与中间元素比较的情况产生了新的区间值low、high值,当出现low>high时算法终止,即不存在值为x的元素。 #include main(void) {inta[10]={1,2,3,4,5,6,7,8,9,10}; intlow,high,mid,n=10,x; printf("请输入一个数x: "); scanf("%d",&x); low=0;high=n-1; while(low<=high) {mid=(low+high)/2; if(x==a[mid])break;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第6章
![提示](https://static.bingdoc.com/images/bang_tan.gif)