第四章构造数据类型.docx
- 文档编号:28091230
- 上传时间:2023-07-08
- 格式:DOCX
- 页数:66
- 大小:200.46KB
第四章构造数据类型.docx
《第四章构造数据类型.docx》由会员分享,可在线阅读,更多相关《第四章构造数据类型.docx(66页珍藏版)》请在冰豆网上搜索。
第四章构造数据类型
第四章构造数据类型
迄今为止,所见到的变量都是简单变量,或称为标量(Scalar),简单变量只具有保存单一数据的能力。
大多数程序设计语言都支持两类构造数据类型:
数组(Array)类型和结构体(Structure)类型。
存储这类数据的变量称为结构变量,也称为构造变量或聚合(Aggregate)变量,这类变量可以存储一个数据的集合。
本章主要介绍这两类构造数据类型及其应用。
4.1数组类型
数组是最常用的数据结构之一,它含有多个数据,并且每个数据都具有相同的数据类型。
也就是说,按一定顺序排列、作为一个整体来处理、具有相同类型(属性)的一组数据可以定义为数组,它用一个统一的名字来标识,占用一片连续的存储单元,每个数据都存储于一个数组元素(Element)中。
数组元素也称为下标变量,它是通过下标(Subscripting)或称为索引(Indexing)来区分的。
在程序设计语言中,常用的数组有一维数组和二维数组。
4.1.1一维数组
最简单的数组类型是一维数组,其数组元素只有1个下标。
使用数组与使用简单变量一样,必须先定义(说明),后使用(引用)。
所不同的是定义数组一次定义了一批相关的变量。
1.一维数组的定义
定义一维数组需要说明数组名、数组元素的个数及数据类型。
在不同的程序设计语言中,定义数组的形式不尽相同,表4-1给出两种典型的定义形式。
表4-1一维数组的定义形式
PASCAL语言
C语言
数组名:
ARRAY[1..N]OF类型标识符
类型标识符数组名[N]
其中:
N为整型常量,确定数组元素的个数,或称为维界。
值得注意的是,在有些语言中,下标的起始值从1开始;有些语言中,下标的起始值从0开始。
例如,用于存放25个学生计算机课程期末考试成绩的数组score可以说明如下。
VARscore:
ARRAY[1..25]OFinteger
表示定义了一个整型数组,数组名为score,该数组具有25个数组元素,下标取值范围为1到25。
2.一维数组元素的引用
数组定义后,才能引用数组中的元素,并且只能逐个引用数组元素而不能一次引用整个数组中的全部元素。
数组元素引用的一般形式为:
数组名[下标]
例如,score[10]表示score数组中索引号为10的数组元素。
下标既可以是整型常量,也可以是整型表达式。
例4-1输入25个学生计算机课程期末考试成绩,并计算平均成绩。
问题分析。
定义一个具有25个元素的数组score,用于存放学生的成绩。
使用循环给数组元素赋值,并将成绩累加到变量sum中。
计算平均成绩average并输出。
编制C源程序如下。
//****************************************************
//*程序名称:
ProcScore.cpp*
//*程序功能:
处理成绩*
//*作者:
FENGJUN*
//*编制时间:
2009年3月20日*
//****************************************************
#include
voidmain()
{
intscore[25];
intn,sum=0,average;
for(n=0;n<25;n++)
{
printf("请输入第%d个学生的成绩:
",n);
scanf("%d",&score[n]);
sum=sum+score[n];
}
average=sum/25;
printf("计算机课程平均成绩average=%d\n",average);
}
数组往往与FOR循环结构结合在一起使用。
这样使数据的处理变得更简洁和更高效。
在实际编程中,经常用到平行数组,这是一些具有相同元素个数的数组,对应数组元素之间存在着联系。
例如,用数组No_Stud存放学生的学号,它与存放学生成绩的数组score就是平行数组,可以将同一个学生的信息存放在具有相同下标的两个数组元素中。
例4-2输入5个学生的学号及计算机课程期末考试成绩,并输出成绩最高者的相关信息。
问题分析。
定义两个平行数组No_Stud与score,分别存放学生的学号和成绩。
设学生学号为1001——1005,学号自动产生,成绩由键盘输入。
使用循环给数组各元素赋值,同时确定成绩最高者。
最高分存入变量max中,对应的数组元素下标用k记录。
学生人数设置为符号常量number。
算法设计如图4-1所示,算法中的变量说明如下。
CONST
number=5
VARNo_Stud:
ARRAY[1..number]OFinteger
score:
ARRAY[1..number]OFinteger
max,n,k:
integer
算法4-1ProcScore1(No_Stud,score,number)
k=0;max=0
Forn=1tonumber
No_Stud[n]=1000+n
输入score[n]
score[n]>max
T
F
max=score[n]
k=n
输出No_Stud[k];score[k]
算法结束
图4-1处理学生成绩
根据算法4-1编制C源程序如下。
//****************************************************
//*程序名称:
ProcScore1.cpp*
//*程序功能:
处理学生成绩*
//*作者:
FENGJUN*
//*编制时间:
2009年3月20日*
//****************************************************
#include
#definenumber5
voidmain()
{
intNo_Stud[number],score[number];
intn,k=0,max=0;
for(n=0;n { No_Stud[n]=1001+n; printf("请输入学生%d的成绩: ",No_Stud[n]); scanf("%d",&score[n]); if(score[n]>max) { max=score[n];k=n; } } printf("计算机课程期末考试成绩最高分是: \n"); printf("学号: %d成绩: %d\n",No_Stud[k],score[k]); } 运行程序得到如下结果: 请输入学生1001的成绩: 87↙ 请输入学生1002的成绩: 64↙ 请输入学生1003的成绩: 79↙ 请输入学生1004的成绩: 92↙ 请输入学生1005的成绩: 85↙ 计算机课程期末考试成绩最高分是: 学号: 1004成绩: 92 注意: 算法中数组的起始下标为1,而程序中数组的起始下标为0,请读者认真对照算法与程序中的修改部分。 另外,学生人数定义为符号常量number,将有利于程序的维护。 4.1.2二维数组 掌握了一维数组,学习二维数组是很容易的。 二维数组的数组元素具有2个下标,第1个下标可以看作是行下标,第2个下标可以看作是列下标,二维数组可以存储一个多行多列的数据集合,在数学上称为矩阵(Matrix)。 使用二维数组,必须先定义(说明),后使用(引用)。 1.二维数组的定义 定义二维数组需要说明数组名、数组元素的数据类型以及所包含的行数和列数。 在不同的程序设计语言中,定义二维数组的形式不尽相同,表4-2给出两种典型的定义形式。 表4-2二维数组的定义形式 PASCAL语言 C语言 数组名: ARRAY[1..M,1..N]OF类型标识符 类型标识符数组名[M][N] 其中: M,N为整型常量,分别确定数组的行数和列数,或称为维界。 值得注意的是,在有些语言中,下标的起始值从1开始;有些语言中,下标的起始值从0开始。 例如,用于存放25个学生的学号和计算机课程期末考试成绩的二维数组No_Score可以说明如下。 VARNo_Score: ARRAY[1..25,1..2]OFinteger 表示定义了一个整型二维数组,数组名为No_Score,该数组具有25行2列共50个数组元素,行下标取值范围为1到25,列下标取值范围为1到2。 2.二维数组元素的引用 二维数组定义后,才能引用数组中的元素,并且只能逐个引用数组元素而不能一次引用整个二维数组中的全部元素。 二维数组元素引用的一般形式如下: 数组名[下标1,下标2]或数组名[下标1][下标2] 在不同的程序设计语言中,二维数组元素引用的形式不尽相同。 下标1表示数组元素所在的行,下标2表示数组元素所在的列,下标1和下标2既可以是整型常量,也可以是整型表达式。 例如,No_Score[10,2]表示二维数组No_Score中行号为10列号为2的数组元素。 例4-3用二维数组处理5个学生的学号及计算机课程期末考试成绩,并输出最高分、最低分和平均分。 问题分析。 定义二维数组No_Score,用于存放学生的学号和成绩。 设学生学号为1001——1005,学号自动产生,成绩由键盘输入。 使用循环给数组各元素赋值,同时确定最高分、最低分以及累加成绩。 最高分存入变量max中,最低分存入变量min中,成绩累加到变量sum中。 计算平均成绩average。 学生人数设置为符号常量number1,每个学生所具有的数据项设置为符号常量number2。 编制C源程序如下。 //**************************************************** //*程序名称: ProcScore2.cpp* //*程序功能: 处理学生成绩* //*作者: FENGJUN* //*编制时间: 2009年3月20日* //**************************************************** #include #definenumber15 #definenumber22 voidmain() { intNo_Score[number1][number2]; intn,max=0,min=100,sum=0,average; for(n=0;n { No_Score[n][0]=1001+n; printf("请输入学生%d的成绩: ",No_Score[n][0]); scanf("%d",&No_Score[n][1]); sum=sum+No_Score[n][1];/*累加成绩*/ if(No_Score[n][1]>max)/*找最高分*/ max=No_Score[n][1]; if(No_Score[n][1] min=No_Score[n][1]; } average=sum/number1;/*计算平均分*/ printf("学号计算机成绩\n"); for(n=0;n printf("%d%d\n",No_Score[n][0],No_Score[n][1]); printf("最高分%d\n",max); printf("最低分%d\n",min); printf("平均分%d\n",average); } 运行程序得到如下结果: 请输入学生1001的成绩: 86↙ 请输入学生1002的成绩: 65↙ 请输入学生1003的成绩: 94↙ 请输入学生1004的成绩: 78↙ 请输入学生1005的成绩: 70↙ 学号计算机成绩 100186 100265 100394 100478 100570 最高分94 最低分65 平均分78 请读者思考,存储最高分的变量max为什么赋初值0,存储最低分的变量min为什么赋初值100。 请画出该程序的N-S流程图。 例4-4已知某学期每个学生都有5门课的成绩,要求计算每个学生的总成绩和平均成绩,并按平均成绩由高到低输出成绩表。 问题分析。 不妨设有3个学生。 定义二维数组No_Score,用于存放学生的相关信息,每一行存放一个学生的相关信息,每个学生都有学号、5门课成绩、总成绩、平均成绩7项数据。 所以需要定义一个3×8的二维数组。 需要处理的问题包括: (1)输入原始数据(每个学生的学号及5门课成绩); (2)计算每个学生的总成绩,存入每一行的第7列;(3)计算每个学生的平均成绩,存入每一行的第8列;(4)按第8列数据进行排序,使最高分存入第1行数组元素,最低分存入第3行数组元素;(5)输出二维数组No_Score。 学生人数设置为符号常量number1,每个学生所具有的数据项设置为符号常量number2。 引入中间变量i、j、sum、t。 算法设计如图4-2所示,算法中的变量说明如下。 CONST number1=3 number2=8 VARNo_Score: ARRAY[1..number1,1..number2]OFinteger i,j,sum,t: integer 算法4-2ProcScore2(No_Score) 输入原始数据 FORi=1TOnumber1&&计算每个学生的总成绩和平均成绩 sum=0 FORj=2to6 sum=sum+No_Score[i,j] No_Score[i,7]=sum;No_Score[i,8]=No_Score[i,7]/5 &&实现排序 No_Score[1,8] T F FORj=1tonumber2 t=No_Score[1,j];No_Score[1,j]=No_Score[2,j];No_Score[2,j]=t No_Score[1,8] T F FORj=1tonumber2 t=No_Score[1,j];No_Score[1,j]=No_Score[3,j];No_Score[3,j]=t No_Score[2,8] T F FORj=1tonumber2 t=No_Score[2,j];No_Score[2,j]=No_Score[3,j];No_Score[3,j]=t FORi=1TOnumber1&&输出成绩表 FORj=1tonumber2 输出No_Score[i,j] 换行 算法结束 图4-2处理成绩表 根据算法4-2编制C源程序如下。 //**************************************************** //*程序名称: ProcScore3.cpp* //*程序功能: 处理学生成绩表* //*作者: FENGJUN* //*编制时间: 2009年3月20日* //**************************************************** #include #definenumber13 #definenumber28 voidmain() {inti,j,sum,t; intNo_Score[number1][number2]={{1001,78,82,93,74,65}, {1002,91,62,71,67,82}, {1003,100,96,88,79,70}}; for(i=0;i {sum=0; for(j=1;j<6;j++) sum=sum+No_Score[i][j]; No_Score[i][6]=sum;No_Score[i][7]=No_Score[i][6]/5; } //实现排序*// if(No_Score[0][7] for(j=0;j {t=No_Score[0][j];No_Score[0][j]=No_Score[1][j];No_Score[1][j]=t; } if(No_Score[0][7] for(j=0;j {t=No_Score[0][j];No_Score[0][j]=No_Score[2][j];No_Score[2][j]=t; } if(No_Score[1][7] for(j=0;j {t=No_Score[1][j];No_Score[1][j]=No_Score[2][j];No_Score[2][j]=t; } //*输出成绩表*// printf("学号成绩1成绩2成绩3成绩4成绩5总分平均分\n"); for(i=0;i {for(j=0;j printf("%6d",No_Score[i][j]); printf("\n"); } } 运行程序得到如下结果: 学号成绩1成绩2成绩3成绩4成绩5总分平均分 10031009688797043386 1001788293746539278 1002916271678237374 注意: 算法中数组的起始下标为1,而程序中数组的起始下标为0,请读者认真对照算法与程序中的修改部分。 由程序可以看出,在定义数组时可以对数组进行初始化。 二维数组常常与二重循环一起使用,以实现对数组元素的简单操作。 在实现排序过程中,虽然只对平均分进行比较,但需要对学生的所有数据项进行交换操作。 在本例中假定学生人数为3人,若以班级为单位,每个班学生人数在50人左右,你是否有解决排序的方案? 有些程序设计语言中,还允许使用多维数组,它与二维数组的定义、引用类似。 数组一旦被定义,它的维数和维界就不会改变。 数组的规模大小是固定不变的,所以数组是静态数据结构,它占用一片连续的存储单元。 由于存储单元是一维结构,所以存储多维数组就有一个次序约定问题。 对于二维数组,可以以行序为主序进行存储,即按行进行存储;也可以以列序为主序进行存储,即按列进行存储。 大多数程序设计语言中是以行序为主序进行存储的。 对于多维数组存储次序的约定,以行序为主序的存储方式可以规定为最右下标优先,从右至左进行存储;以列序为主序的存储方式可以规定为最左下标优先,从左至右进行存储。 4.1.3查找 查找(Searching)也称为检索,它是数据处理中经常使用的一种最重要、最基本的运算。 所谓查找就是在数组中查找某个特定的数据。 查找结果有两种: 一种是在数组中找到了所需要的数据,称为“查找成功”,则输出该数据的有关信息或索引号;另一种是数组中不存在所找数据,称为“查找失败”,则输出找不到的信息。 衡量一个查找算法效率的主要标准是: 在查找过程中,需要进行的平均比较次数,也称为查找算法的平均查找长度(AverageSearchLength),用ASL(x)表示。 不失一般性,假定一维数组a具有n个数组元素,数组元素的类型为整型数据。 对于查找方法A,为了计算ASL(A),假定数组a中的数据a[i](1≤i≤n)被查找的概率为pi,于是有 下面介绍数组的两种基本查找方法,即顺序查找和二分查找。 1.顺序查找 顺序查找(SequenceSearch)是最基本、最简单的查找方法。 该方法是将数组中的数组元素a[1]、a[2]、…、a[n]依次同要查找的数据进行比较,若找到所需数据,则查找成功;若找遍整个数组,仍未找到所需要的数据,则查找失败。 显然 一般情况下,对于一切i都有pi=1/n。 即通常假定数组中的所有数组元素都具有相同的使用频率。 此时 上式说明,对于数组,在每个数据使用频率相同的情况下,采用顺序查找法,平均要检查所有数据的一半。 所以,顺序查找算法的时间复杂度为O(n)。 例4-5设给定一批整型数据,查找数据x。 问题分析。 定义一个一维数组a,用于存放这批整型数据。 待查找数据x由键盘输入。 用顺序查找法在数组a中查找数据x。 若查找成功,则输出数据x的索引号i;若查找失败,则输出“没有找到数据x”。 编制C源程序如下。 //**************************************************** //*程序名称: Sequence_Search.cpp* //*程序功能: 顺序查找* //*作者: FENGJUN* //*编制时间: 2009年3月20日* //**************************************************** #include #definen20 voidmain() { inta[n+1]={78,52,28,9,74,65,22,34,91,62,71,67,82,18,45,53,6,88,79,70}; inti=0,x; printf("请输入要查找的数据(范围0到100)x="); scanf("%d",&x); a[20]=x; while(x! =a[i]) i++; if(n! =i) printf("所查找的数据x=%d的索引号为: %d\n",x,i); else printf("没有找到数据x=%d\n",x); } 运行程序得到如下结果: ①请输入要查找的数据(范围0到100)x=88↙ 所查找的数据x=88的索引号为: 17 ②请输入要查找的数据(范围0到100)x=90↙ 没有找到数据x=90 请读者思考,给定整数20个,为什么说明数组a具有21个数组元素? 程序中第15行语句a[20]=x的作用是什么? 若删除该语句,会出现什么情况? 你还有其它解决方案吗? 请画出该程序的N-S流程图。 2.二分查找 当数组中的数据有序时,可以采用二分查找法。 二分查找(BinarySearch)又称为折半查找,它是一种效率较高的查找方法。 二分查找法的基本思想是: 将数组中的n个数据按从小到大的次序依次存放在数组a[1..n]中,要求查找数据x。 开始时,令low=1,high=n,然后反复执行“平分步骤”。 这里,辅助变量low、high表示当前的查找范围缩小到子序列a[low..high]。 所谓平分步骤是指: 记mid=low+high)DIV2是余下的数据序列a[low..high]的中点索引号。 ①若x=a[mid],则找到所需数据,查找过程结束;②若xa[mid],则令low=mid+1,即查找范围缩小到子序列a[mid+1..high]。 二分查找算法设计如图4-3所示,算法中的变量说明如
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第四 构造 数据类型
![提示](https://static.bdocx.com/images/bang_tan.gif)