C语言程序设计与数据结构_第1页
C语言程序设计与数据结构_第2页
C语言程序设计与数据结构_第3页
C语言程序设计与数据结构_第4页
C语言程序设计与数据结构_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C语言程序设计与数据结构第1页/共39页主要内容7.1一维数组7.2二维数组7.3字符数组7.4数组在函数中的应用7.5折半查找7.6数组元素排序7.7典型习题分析解答第2页/共39页

7.1一维数组

7.1.1一维数组的定义与初始化一维数组的定义

一维数组的定义格式为:类型说明符数组名[常量表达式];

说明:

(1)数组的类型指数组元素的取值类型。对于上例,即说明该数组a中的10个元素都是整型。(2)数组名必须是合法标识符,也就是说必须符合标识符的命名规则;(3)数组名不能与同一程序中的其它变量同名;(4)若用方括号中的整数n来表示数组元素的总数,则数组的第一个元素的下标为0(称为数组下标的下界),最后一个为n-1(称为数组下标的上界)。对于上例,数组中含有10个元素,分别是:a[0],a[1],a[2],……,a[9]。(5)不能在方括号中用变量来表示元素的个数。

(6)允许在同一个说明中,说明相同类型的多个数组和多个变量。(7)可以使用在编译预处理#define中定义的符号常量。第3页/共39页

一维数组的初始化

初始化赋值的一般形式为:

类型说明符数组名[常量表达式]={值,值……值};其中在{}中的各数据值即为各元素的初值,各值之间用逗号间隔。例如:inta[10]={0,1,2,3,4,5,6,7,8,9};说明:(1)可以只给部分元素赋初值。当{}中值的个数少于元素个数时,只给前面部分元素赋值。例如:inta[10]={0,1,2,3,4};表示只给a[0]~a[4]这5个元素赋值,而后5个元素自动赋0值。(2)能给元素逐个赋值,但不能给数组整体赋值。例如给十个元素全部赋1值,只能写为:inta[10]={1,1,1,1,1,1,1,1,1,1};而不能写为:inta[10]=1;(3)如给全部元素赋值,则在数组说明中,可以不给出数组元素的个数。例如:inta[5]={1,2,3,4,5};可写为:inta[]={1,2,3,4,5};第4页/共39页7.1.2一维数组元素的引用数组元素引用的一般形式为:

数组名[下标]其中的下标只能为整型常量或整型表达式。如果为小数时,C编译将自动取整。例如,a[6],b[i+j],b[i++]都是合法的数组元素。数组元素通常也称为下标变量。必须先定义数组,才能使用下标变量。在C语言中只能逐个地使用下标变量,而不能一次引用整个数组。例如,单独使用一个下标变量:

inta[10];a[7]=6;第5页/共39页7.1.3一维数组元素的赋值数组定义之后,如果不对其进行初始化,则其值可通过赋值语句获或者可从键盘、文件等读取获得。现以从键盘接收数据为例:【例7.1】从键盘输入十个数据给数组a赋值,然后把数组a的值复制到数组b中。

main(){inta[10],b[10],i;for(i=0;i<10;i++)scanf("%d",&a[i]);for(i=0;i<10;i++)b[i]=a[i];for(i=0;i<10;i++)printf("%d",b[i]);}第6页/共39页7.1.4顺序查找

顺序查找即为从数组的一端开始,逐个进行数组元素的值和给定值x的比较,若某个元素的值和给定值x相等,则查找成功;反之,若直至最后一个数组元素,其值和给定值x都不相等,则表明数组中没有所查的数据,查找不成功。【例7.2】已知存放在a数组中的数据两两不相同,在a数组中查找和x值相同的元素的位置。若找到,输出该值和其在a数组中的位置;若没找到,输出相应的提示信息。#defineN100main(){inta[N],x,n,i,flag=-1;printf("Inputn:\n");scanf("%d",&n);for(i=0;i<n;i++)scanf("%d",&a[i]);printf("Inputx:\n");scanf("%d",&x);第7页/共39页for(i=0;i<n;i++)if(a[i]==x){flag=i;break;}if(flag!=-1)printf("%dindexis%d",x,flag+1);elseprintf("%ddonntbefounded!\n",x);对于上例,也可以通过设监视哨的方法对数组倒着查找,代码见课本。第8页/共39页

7.2二维数组

二维数组:数组元素是双下标变量的数组。二维数组的数组素可以看作是排列为行列的形式(矩阵)。二维数组也用统一的数组名标识,第一个下标表示行,第二个下标表示列。下标从0开始。7.2.1二维数组的定义与初始化二维数组的定义二维数组定义的一般形式是:

类型说明符数组名[常量表达式1][常量表达式2];其中常量表达式1表示第一维下标的长度,常量表达式2表示第二维下标的长度。例如:inta[3][4];说明了一个三行四列的数组,数组名为a,其下标变量的类型为整型。该数组的下标变量共有3×4个,即:a[0][0],a[0][1],a[0][2],a[0][3]a[1][0],a[1][1],a[1][2],a[1][3]a[2][0],a[2][1],a[2][2],a[2][3]如何在一维存储器中存放二维数组,可有两种方式:一种是按行排列,即放完一行之后顺次放入第二行。另一种是按列排列,即放完一列之后顺次放入第二列。在C语言中,二维数组是按行排列的。第9页/共39页二维数组的初始化二维数组可按行分段赋值,也可按行连续赋值。二维数组的初始化的几种常见形式:(1)分行给二维数组所有元素赋初值例如:inta[2][4]={{1,2,3,4},{5,6,7,8}};(2)不分行给二维数组所有元素赋初值例如:inta[2][4]={1,2,3,4,5,6,7,8};(3)给二维数组所有元素赋初值,二维数组第一维的长度可以省略(编译程序可计算出长度)例如:inta[][4]={1,2,3,4,5,6,7,8};或:inta[][4]={{1,2,3,4},{5,6,7,8}};(4)对部分元素赋初值例如:inta[2][4]={{1,2},{5}};

第10页/共39页7.2.2二维数组元素的引用定义了二维数组后,就可以引用该数组的所有元素。引用形式:数组名[下标1][下标2]例如:a[1][2]表示a数组第二行第三列的元素。下标变量和数组说明在形式中有些相似,但这两者具有完全不同的含义。数组说明的方括号中给出的是某一维的长度,即可取下标的最大值;而数组元素中的下标是该元素在数组中的位置标识。第11页/共39页7.2.3二维数组元素的赋值同一维数组一样,若二维数组定义之后,不对其进行初始化,则其值可通过赋值语句获得,或者可从键盘、文件等读取获得。现以从键盘接收数据为例:【例7.3】通过键盘给3×3的二维数组输入数据,第一行赋1,2,3,第二行赋10,20,30,第三行输入100,200,300,然后输出此二维数组。main(){inta[3][3],i,j;for(i=0;i<3;i++)for(j=0;j<3;j++)scanf("%d",&a[i][j]);for(i=0;i<3;i++){for(j=0;j<3;j++) printf("%4d",a[i][j]);printf("\n");}}第12页/共39页7.3字符数组用来存放字符型数据的数组称为字符数组。字符数组中的一个元素存放一个字符。

7.3.1字符数组的定义、初始化字符数组的定义与前面介绍的数值数组定义相同。其定义格式为:

char数组名[下标总数];例如:charc[10]={‘c’,‘’,‘p’,‘r’,‘o’,‘g’,‘r’,‘a’,’m’};赋值后各元素的值为:c[0]的值为‘c’,c[1]的值为‘’,c[2]的值为‘p’,……,c[8]的值为‘m’,其中c[9]未赋值,系统自动赋予’\0’值。当对全体元素赋初值时也可以省去长度说明。例如:charc[]={‘c’,‘’,‘p’,‘r’,‘o’,‘g’,‘r’,‘a’,’m’};这时C数组的长度自动定为9。另外,我们还可以将一个字符串赋给一个字符数组。字符串,是指若干有效字符的序列。如:”a”,”abc”。注意:由于系统在存储字符串常量时,会在串尾自动加上1个结束标志,所以无需人为地再加1个。第13页/共39页7.3.2字符串处理函数

字符串标准函数的原型在头文件string.h中。1.输出字符串──puts()函数(1)调用方式:puts(字符数组)(2)函数功能:把字符数组中所存放的字符串,输出到标准输出设备中去,并用‘\n’取代字符串的结束标志‘\0’。所以用puts()函数输出字符串时,不要求另加换行符。(3)使用说明:①字符串中允许包含转义字符,输出时产生一个控制操作。②该函数一次只能输出一个字符串,而printf()函数也能用来输出字符串,且一次能输出多个。【例7.5】下列程序的输出结果是:#include<stdio.h>main(){charc[]="BASIC\ndBASE";puts(c);}运行结果为:BASICdBASE第14页/共39页2.输入字符串──gets()函数(1)调用方式:gets(字符数组)(2)函数功能:从标准输入设备(stdin)──键盘上,读取1个字符串(可以包含空格),并将其存储到字符数组中去。(3)使用说明

1)gets()读取的字符串,其长度没有限制,编程者要保证字符数组有足够大的空间,存放输入的字符串。

2)该函数输入的字符串中允许包含空格,而在scanf()函数中使用%s接收字符串时,空格做为字符串的结束标志。【例7.6】#include<stdio.h>main(){charst[15];printf("inputstring:\n");gets(st);puts(st);}输入:cprogram显示:cprogram第15页/共39页3.字符串比较──strcmp()函数(1)调用方式:strcmp(字符串1,字符串2)其中“字符串”可以是串常量,也可以是1维字符数组。(2)函数功能:比较两个字符串的大小。如果:字符串1=字符串2,函数返回值等于0;字符串1<字符串2,函数返回值负整数;字符串1>字符串2,函数返回值正整数。(3)使用说明①如果一个字符串是另一个字符串从头开始的子串,则母串为大。②不能使用关系运算符“==”来比较两个字符串,只能用strcmp()函数来处理。【例7.7】#include<string.h>main(){intk;charst1[15],st2[]="CLanguage";printf("inputastring:\n");gets(st1);k=strcmp(st1,st2);if(k==0)printf("st1=st2\n");if(k>0)printf("st1>st2\n");if(k<0)printf("st1<st2\n");}第16页/共39页4.拷贝字符串──strcpy()函数(1)调用方式:strcpy(字符数组1,字符数组2)(2)函数功能:将“字符数组2”完整地复制到“字符数组1”中,字符数组中原有内容被覆盖。(3)使用说明:①字符数组必须定义得足够大,以便容纳复制过来的字符串。复制时,连同结束标志'\0'一起复制。②不能用赋值运算符“=”将一个字符串直接赋值给一个字符数组,只能用strcpy()函数来处理。【例7.8】#include<string.h>main(){charst1[15],st2[]="CLanguage";strcpy(st1,st2);puts(st1);printf("\n");}运行结果为:CLanguage第17页/共39页5.连接字符串──strcat()函数(1)调用方式:strcat(字符数组,字符串)(2)函数功能:把“字符串”连接到“字符数组”中的字符串尾端,并存储于“字符数组”中。“字符数组”中原来的结束标志,被“字符串”的第一个字符覆盖,而“字符串”在操作中未被修改。(3)使用说明①由于没有边界检查,编程者要注意保证“字符数组”定义得足够大,以便容纳连接后的目标字符串;否则,会因长度不够而产生问题。②连接前两个字符串都有结束标志'\0',连接后“字符数组”中存储的字符串的结束标志'\0'被舍弃,只在目标串的最后保留一个'\0'。【例7.9】把初始化赋值的字符数组与动态赋值的字符串连接起来。#include<string.h>main(){charst1[30]="Mynameis";/*注意长度为30*/charst2[10];printf("Inputyourname:");gets(st2);strcat(st1,st2);puts(st1);}第18页/共39页6.求字符串长度──strlen()函数(len是length的缩写)(1)调用方式:strlen(字符串)(2)函数功能:求字符串(常量或字符数组)的实际长度(不包含结束标志)。【例7.10】#include<string.h>main(){intk;charst[]="Clanguage";k=strlen(st);printf("Thelenthofthestringis%d\n",k);}运行结果为:Thelenthofthestringis10第19页/共39页7.4数组在函数中的应用

数组可以作为函数的参数使用,进行数据传送。数组用作函数参数有两种形式:一种是把数组元素(下标变量)作为实参使用;另一种是把数组名作为函数的形参和实参使用。数组元素作函数实参数组元素就是下标变量,它与普通变量并无区别。因此它作为函数实参使用与普通变量是完全相同的,在发生函数调用时,把作为实参的数组元素的值传送给形参,实现单向的值传送。【例7.11】编程实现对一数组中所有元素取绝对值.#include<math.h>main(){inta[5]={1,-5,4,-7,-4},i;for(i=0;i<5;i++)a[i]=f(a[i]);for(i=0;i<5;i++)printf("%4d",a[i]);}intf(intx){ if(x<0)return-x; elsereturnx;}第20页/共39页2、数组名作为函数参数

数组名就是数组的首地址,因此在数组名作函数参数时所进行的传送是地址的传送,所以要求形参必须是和实参类型相同的数组名,对于形参必须有明确的数组说明。在实参与形参进行“值传递”时,是把实参数组的首地址赋予形参数组名。形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间。【例7.12】数组a中存放了一个学生5门课程的成绩,求平均成绩。floataver(floata[5]){inti;floatav,s=a[0];for(i=1;i<5;i++)s=s+a[i];av=s/5;returnav;}voidmain(){floatsco[5],av;inti;printf("\ninput5scores:\n");for(i=0;i<5;i++)scanf("%f",&sco[i]);av=aver(sco);printf("averagescoreis%5.2f",av);}第21页/共39页7.5折半查找折半查找又称二分查找,是针对有序表进行查找的简单、有效而又较常用的方法。所谓有序表,即要求表中的各元素按关键字的值有序(升序或降序)存放。折半查找不像顺序查找那样,从第一个记录开始逐个顺序搜索,其基本思想是:首先选取表中间位置的记录,将其关键字与给定关键字k进行比较,若相等,则查找成功;否则,若k值比该关键字值大,则要找的元素一定在表的后半部分(或称右子表),则继续对右子表进行折半查找;若k值比该关键字值小,则要找的元素一定在表的前半部分(左子表),同样应继续对左子表进行折半查找。每进行一次比较,要么找到要查找的元素,要么将查找的范围缩小一半。如此递推,直到查找成功或把要查找的范围缩小为空(查找失败)。设表的长度为n,表的被查找部分的头为low,尾为high,初始时,low=1,high=n,k为关键字的值。

第22页/共39页【例7.16】已知如下11个数据元素的有序表(关键字即为数据元素的值):

现要查找关键字为21和85的数据元素。

假设指针low和high分别指示待查元素所在范围的下界和上界,指针mid指示区间的中间位置,即mid=(low+high)/2。在此例中,low和high的初值分别为1和11,即[1,11]为待查范围。

第23页/共39页先看给定值key=21的查找过程:

a[mid]与给定值key相比较,因为a[mid]>key,说明待查元素若存在,必在区间[low,mid-1]的范围内,则令指针high指向第mid-1个元素,重新求得mid=(1+5)/2=3

仍以a[mid]和key相比,因为a[mid]<key,说明待查元素若存在,必在[mid+1,high]范围内,则令指针low指向第mid+1个元素,求得mid的新值为4,比较a[mid]和key,因为相等,则查找成功,所查元素在表中序号等于指针mid的值。

第24页/共39页源程序:#defineN50intbinsrch(intr[],intn,intk){intmid,low,high,find;low=1;high=n;find=0;/*置区间初值*/while((low<=high)&&(!find)){mid=(low+high)/2;/*求中点*/if(k==r[mid])find=1;/*已查到*/elseif(k>r[mid])low=mid+1;/*在后半区间查找*/elsehigh=mid-1;/*在前半区间查找*/}if(find)return(mid);/*查找成功,返回找到元素的位置*/elsereturn(0);/*查找不成功,返回0标记*/}第25页/共39页main(){inta[N],n,i,k,f;printf("请输入数据元素的个数:\n");scanf("%d",&n);printf("请输入数据元素:\n");for(i=1;i<=n;i++)scanf("%d",&a[i]);printf("请输入要查找的数据:\n");scanf("%d",&k);f=binsrch(a,n,k);if(f==0)printf("值为%d的元素不存在。\n",k);elseprintf("%d在数组中的位置为%d",k,f);}第26页/共39页7.6数组元素排序排序(Sorting)是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列.7.6.1插入排序线性插入排序的基本思想是:第1遍,将初始文件中的第1个记录看作有序的序列,然后从第2个记录开始逐个插入前边的有序序列,并使插入后,前边仍有序。第i趟直接插入排序的操作为:在含有i-1个记录的有序子序列r[1..i-1]中插入一个记录r[i]后,变成含有i个记录有序子序列r[1..i]。为了在查找插入位置的过程中避免数组下标出界,在r[0]处设置监视哨,将r[i]拷贝到r[0]处,当从i-1起往前搜索的过程中,可以同时后移记录。直至整个数组变成有序为止。整个排序过程共进行n-1趟插入。第27页/共39页【例7.17】将数组(43,21,89,15,43,28)中的元素进行升序排列。第28页/共39页其源程序为:#defineN50voidinsertsort(intr[],intn){inti,j; for(i=2;i<=n;i++)/*共进行n-1趟*/{r[0]=r[i];/*r[0]为监视哨,也可做下边循环结束标志*/j=i-1;while(r[j]>r[0]){ r[j+1]=r[j];j--;}r[j+1]=r[0];}}第29页/共39页main(){inta[N],n,i;printf("请输入数据元素的个数:\n");scanf("%d",&n);printf("请输入数据元素:\n");for(i=1;i<=n;i++)scanf("%d",&a[i]);insertsort(a,n);printf("升序排列的结果为:\n");for(i=1;i<=n;i++)printf("%5d",a[i]);}第30页/共39页7.6.2折半插入排序

在线性插入排序中,我们采用顺序查找法来确定记录的插入位置。如果(R1,R2,…,Ri-1)是有序子文件,我们可以采用折半查找法来确定R1的插入位置,这种排序称为折半插入排序。【例7.18】将数组(43,21,89,15,43,28)中的元素进行升序排列。#defineN50voidbinarysort(intr[],intn)/*按关键字递增次序对r[1],r[2],……,r[n]进行折半插入排序*/{inti,j,l,h,mid; for(i=2;i<=n;i++){r[0]=r[i]; l=1; h=i-1;while(l<=h){mid=(l+h)/2;if(r[0]<r[mid])h=mid-1;elsel=mid+1;}for(j=i-1;j>=l;j--)r[j+1]=r[j];r[l]=r[0];}}第31页/共39页main(){inta[N],n,i;printf("请输入数据元素的个数:\n");scanf("%d",&n);printf("请输入数据元素:\n");for(i=1;i<=n;i++)scanf("%d",&a[i]);binarysort(a,n);printf("升序排列的结果为:\n");for(i=1;i<=n;i++)printf("%5d",a[i]);}第32页/共39页7.7典型习题分析解答

【例7.19】若有说明:inta[3][4],则对数组a元素非法引用的是。A)a[0][2*1]B)a[1][3]C)a[4-2][0]D)a[0][4]分析:本题考察对于二维数组元素引用的原则。对以上述定义的二维数组,其最大下标的元素对应:a[2][3].答案:D【例7.20】若二维数组有m列,则在a[i][j]之前的元素的个数为A.j*m+iB.i*m+jC.i*m+j-1D.j*m+i-1分析:在C语言中,由于二维数组在内存中是按照行优先的顺序存储的,且下标的起始值为0,因此在a[i][j]之前有i*m+j个。答案:B【例7.21】以下选项中合法的数组说明语句是A.ina[]=”string”B.inta[5]={0,1,2,3,4,5}C.chara=”string”D.chara[5]={0,1,2,3,4,5}分析:在C语言中,字符变量中存放的是与字符对应的ASCII码值,数值0,1,2,3,4,5对应的字符虽然是不可显示的字符,但是这些都可以作为控制字符。此时,数组的大小有后面的初始化数据的数量决定。答案:D第33页/共39页【例7.22】以下程序的输出结果是:

voidreverse(inta[],intn)

{inti,t;for(i=0;i<n/2;i++)

{t=a[i];a[i]=a[n-1-i];a[n-1-i]=t;}}main()

{intb[10]={1,2,3,4,5,6,7,8,9,10};inti,s=0;reverse(b,8);for(i=6;i<10;i++)s+=b[i];printf("%d\n",s);}A)22B)10C)34D)分析:在main函数中,调用reverse函数将b数组中的前8个成员进行互置,执行完毕后,b数组中的成员为{8,7,6,5,4,3,2,1,9,10},然后再执行for循环结构,将b[6],b[7]...b[9]的值相加,结果为22。答案:A第34页/共39页【例7.23】当运行以下程序时,从键盘输入;AhaMA(空格)Aha<CR>,则下面程序的运行结果是#include<stdio.h>main(){chars[80],c=′a′;inti=0;scanf("%s",s);while(s[i]!=′\n′){if

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论