数据结构习题解析第1章.docx
《数据结构习题解析第1章.docx》由会员分享,可在线阅读,更多相关《数据结构习题解析第1章.docx(27页珍藏版)》请在冰豆网上搜索。
![数据结构习题解析第1章.docx](https://file1.bdocx.com/fileroot1/2023-2/1/6b99b9fc-516d-4d6b-a6b8-ba0497b31a49/6b99b9fc-516d-4d6b-a6b8-ba0497b31a491.gif)
数据结构习题解析第1章
第1章绪论
一、复习要点
本章主要讨论贯穿和应用于整个《数据结构》课程始终的基本概念和性能分析方法。
学习本章的内容,将为后续章节的学习打下良好的基础。
本章复习的要点:
1、基本知识点
要求理解的概念包括:
数据,数据对象,数据元素或数据成员,数据结构,数据类型,数据抽象,抽象数据类型,数据结构的抽象层次,面向对象,对象与类的关系,类的继承关系,对象间的消息通信等。
需要对各个概念进行区分与比较。
例如,按照面向对象建模技术的要求,把建立对象类作为一个层次,把建立对象间的关系(即建立结构)作为另外的层次。
因此,在软件开发中做数据结构设计时,不但要设计对象–类,类的属性,类的操作,还要建立类的实例之间的关系。
从这个角度考虑,把数据结构定义为数据对象及对象中各数据成员之间关系的集合是合理的。
又例如,类class或struct与C中的结构类型struct的区别在于前者不但有对象的状态描述(数据成员),还加入了操作(成员函数),描述对象的行为,这样可以体现一个完整的实体概念,而后者不行。
再例如,传统的数据结构概念从数据结构的逻辑结构、物理结构和相关操作等3个方面进行讨论。
它反映了数据结构设计的不同层次:
逻辑结构属于问题解决范畴,物理结构是逻辑结构在计算机中的存储方式。
但在面向对象开发模式中,本课程中涉及的数据结构都属于基本数据结构,但有的属于应用级的数据结构,如稀疏矩阵,字符串,栈与队列,优先级队列,图等;有的属于实现级的数据结构,如数组,链表,堆,索引,散列表等。
2、有关算法的概念和简单的算法性能分析方法
算法的5个特性表明算法的实现属于面向过程的开发模式,即传统的“输入-计算-输出”模式。
算法的应用要求明确算法的时间和空间代价。
因此,必须理解算法的定义和算法的5个特性,掌握简单的时间复杂度估计和空间复杂度估计方法(不讨论程序复杂性)。
3、描述语言
要求数据结构的描述既要体现算法的逻辑,又要体现面向对象的概念,需要一种能够兼有面向对象和面向过程双重特性的描述语言。
传统的Pascal语言和C语言只是面向过程的语言,不能适应面向对象的开发模式。
因此,采用C++语言描述。
要求学员基本掌握C++语言的基本概念和用C++语言编写应用程序的基本技术。
例如,用类定义抽象数据类型的方式,定义模板类、抽象类的方法,函数与参数的定义,建立类(公有、私有)继承的方法,例外与异常的处理等等,都需要掌握。
二、难点与重点
1、基本概念:
理解什么是数据、数据对象、数据元素、数据结构、数据的逻辑结构与物理结构、数据结构的抽象层次。
2、面向对象概念:
理解什么是数据类型、抽象数据类型、数据抽象和信息隐蔽原则。
了解什么是面向对象。
Ø抽象数据类型的封装性
ØCoad与Yourdon定义:
面向对象=对象+类+继承+通信。
Ø面向对象系统结构的稳定性
Ø面向对象方法着眼点在于应用问题所涉及的对象
3、算法与算法分析:
理解算法的定义、算法的特性、算法的时间代价、算法的空间代价。
Ø算法与程序的不同之处需要从算法的特性来解释
Ø算法的正确性是最主要的要求
Ø算法的可读性是必须考虑的
Ø程序的程序步数的计算与算法的事前估计
Ø程序的时间代价是指算法的渐进时间复杂性度量
三、教材中习题的解析
1-1什么是数据?
它与信息是什么关系?
【解答】
什么是信息?
广义地讲,信息就是消息。
宇宙三要素(物质、能量、信息)之一。
它是现实世界各种事物在人们头脑中的反映。
此外,人们通过科学仪器能够认识到的也是信息。
信息的特征为:
可识别、可存储、可变换、可处理、可传递、可再生、可压缩、可利用、可共享。
什么是数据?
因为信息的表现形式十分广泛,许多信息在计算机中不方便存储和处理,例如,一个大楼中4部电梯在软件控制下调度和运行的状态、一个商店中商品的在库明细表等,必须将它们转换成数据才能很方便地在计算机中存储、处理、变换。
因此,数据(data)是信息的载体,是描述客观事物的数、字符、以及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。
在计算机中,信息必须以数据的形式出现。
1-2什么是数据结构?
有关数据结构的讨论涉及哪三个方面?
【解答】
数据结构是指数据以及相互之间的关系。
记为:
数据结构={D,R}。
其中,D是某一数据对象,R是该对象中所有数据成员之间的关系的有限集合。
有关数据结构的讨论一般涉及以下三方面的内容:
1数据成员以及它们相互之间的逻辑关系,也称为数据的逻辑结构,简称为数据结构;
②数据成员极其关系在计算机存储器内的存储表示,也称为数据的物理结构,简称为存储结构;
3施加于该数据结构上的操作。
数据的逻辑结构是从逻辑关系上描述数据,它与数据的存储不是一码事,是与计算机存储无关的。
因此,数据的逻辑结构可以看作是从具体问题中抽象出来的数据模型,是数据的应用视图。
数据的存储结构是逻辑数据结构在计算机存储器中的实现(亦称为映像),它是依赖于计算机的,是数据的物理视图。
数据的操作是定义于数据逻辑结构上的一组运算,每种数据结构都有一个运算的集合。
例如搜索、插入、删除、更新、排序等。
1-3数据的逻辑结构分为线性结构和非线性结构两大类。
线性结构包括数组、链表、栈、队列、优先级队列等;非线性结构包括树、图等、这两类结构各自的特点是什么?
【解答】
线性结构的特点是:
在结构中所有数据成员都处于一个序列中,有且仅有一个开始成员和一个终端成员,并且所有数据成员都最多有一个直接前驱和一个直接后继。
例如,一维数组、线性表等就是典型的线性结构
非线性结构的特点是:
一个数据成员可能有零个、一个或多个直接前驱和直接后继。
例如,树、图或网络等都是典型的非线性结构。
1-4.什么是抽象数据类型?
试用C++的类声明定义“复数”的抽象数据类型。
要求
(1)在复数内部用浮点数定义它的实部和虚部。
(2)实现3个构造函数:
缺省的构造函数没有参数;第二个构造函数将双精度浮点数赋给复数的实部,虚部置为0;第三个构造函数将两个双精度浮点数分别赋给复数的实部和虚部。
(3)定义获取和修改复数的实部和虚部,以及+、-、*、/等运算的成员函数。
(4)定义重载的流函数来输出一个复数。
【解答】
抽象数据类型通常是指由用户定义,用以表示应用问题的数据模型。
抽象数据类型由基本的数据类型构成,并包括一组相关的服务。
//在头文件complex.h中定义的复数类
#ifndef_complex_h_
#define_complex_h_
#include
classcomlex{
public:
complex(){Re=Im=0;}//不带参数的构造函数
complex(doubler){Re=r;Im=0;}//只置实部的构造函数
complex(doubler,doublei){Re=r;Im=i;}//分别置实部、虚部的构造函数
doublegetReal(){returnRe;}//取复数实部
doublegetImag(){returnIm;}//取复数虚部
voidsetReal(doubler){Re=r;}//修改复数实部
voidsetImag(doublei){Im=i;}//修改复数虚部
complex&operator=(complex&ob){Re=ob.Re;Im=ob.Im;}//复数赋值
complex&operator+(complex&ob);//重载函数:
复数四则运算
complex&operator–(complex&ob);
complex&operator*(complex&ob);
complex&operator/(complex&ob);
friendostream&operator<<(ostream&os,complex&c);//友元函数:
重载<<
private:
doubleRe,Im;//复数的实部与虚部
};
#endif
//复数类complex的相关服务的实现放在C++源文件complex.cpp中
#include
#include
#include“complex.h”
complex&complex:
:
operator+(complex&ob){
//重载函数:
复数加法运算。
complexresult;
result.Re=Re+ob.Re;result.Im=Im+ob.Im;
returnresult;
}
complex&complex:
:
operator–(complex&ob){
//重载函数:
复数减法运算
complexresult;
result.Re=Re–ob.Re;result.Im=Im–ob.Im;
returnresult;
}
complex&complex:
:
operator*(complex&ob){
//重载函数:
复数乘法运算
complexresult;
result.Re=Re*ob.Re–Im*ob.Im;result.Im=Im*ob.Re+Re*ob.Im;
returnresult;
}
complex&complex:
:
operator/(complex&){
//重载函数:
复数除法运算
doubled=ob.Re*ob.Re+ob.Im*ob.Im;
complexresult;
result.Re=(Re*ob.Re+Im*ob.Im)/d;result.Im=(Im*ob.Re–Re*ob.Im)/d;
returnresult;
}
friendostream&operator<<(ostream&os,complex&ob){
//友元函数:
重载<<,将复数ob输出到输出流对象os中。
returnos<=0.0)?
“+”:
“-”<}
1-5用归纳法证明:
(1)
(2)
(3)
【证明】略
1-6什么是算法?
算法的5个特性是什么?
试根据这些特性解释算法与程序的区别。
【解答】
通常,定义算法为“为解决某一特定任务而规定的一个指令序列。
”一个算法应当具有以下特性:
①有输入。
一个算法必须有0个或多个输入。
它们是算法开始运算前给予算法的量。
这些输入取自于特定的对象的集合。
它们可以使用输入语句由外部提供,也可以使用赋值语句在算法内给定。
②有输出。
一个算法应有一个或多个输出,输出的量是算法计算的结果。
③确定性。
算法的每一步都应确切地、无歧义地定义。
对于每一种情况,需要执行的动作都应严格地、清晰地规定。
④有穷性。
一个算法无论在什么情况下都应在执行有穷步后结束。
⑤有效性。
算法中每一条运算都必须是足够基本的。
就是说,它们原则上都能精确地执行,甚至人们仅用笔和纸做有限次运算就能完成。
算法和程序不同,程序可以不满足上述的特性(4)。
例如,一个操作系统在用户未使用前一直处于“等待”的循环中,直到出现新的用户事件为止。
这样的系统可以无休止地运行,直到系统停工。
此外,算法是面向功能的,通常用面向过程的方式描述;程序可以用面向对象方式搭建它的框架。
1-7设n为正整数,分析下列各程序段中加下划线的语句的程序步数。
(1)for(inti=1;i<=n;i++)
(2)x=0;y=0;
for(intj=1;j<=n;j++){for(inti=1;i<=n;i++)
c[i][j]=0.0;for(intj=1;j<=i;j++)
for(intk=1;k<=n;k++)for(intk=1;k<=j;k++)
c[i][j]=c[i][j]+a[i][k]*b[k][j];x=x+y;
}
(3)inti=1,j=1;(4)inti=1;
while(i<=n&&j<=n){do{
i=i+1;j=j+i;for(intj=1;j<=n;j++)
}i=i+j;
}while(i<100+n);
【解答】
(1)
(2)
(3)i=1时,i=2,j=j+i=1+2=2+1,
i=2时,i=3,j=j+i=(2+1)+3=3+1+2,
i=3时,i=4,j=j+i=(3+1+2)+4=4+1+2+3,
i=4时,i=5,j=j+i=(4+1+2+3)+5=5+1+2+3+4,
……
i=k时,i=k+1,j=j+i=(k+1)+(1+2+3+4+…+k),
解出满足上述不等式的k值,即为语句i=i+1的程序步数。
(4)
一般地,
求出满足此不等式的k值,即为语句i=i+j的程序步数。
1-8试编写一个函数计算n!
*2n的值,结果存放于数组A[arraySize]的第n个数组元素中,0≤n≤arraySize。
若设计算机中允许的整数的最大值为maxInt,则当n>arraySize或者对于某一个k(0≤k≤n),使得k!
*2k>maxInt时,应按出错处理。
可有如下三种不同的出错处理方式:
(1)用cerr<<及exit
(1)语句来终止执行并报告错误;
(2)用返回整数函数值0,1来实现算法,以区别是正常返回还是错误返回;
(3)在函数的参数表设置一个引用型的整型变量来区别是正常返回还是某种错误返回。
试讨论这三种方法各自的优缺点,并以你认为是最好的方式实现它。
【解答】
#include"iostream.h"
#definearraySize100
#defineMaxInt0x7fffffff
intcalc(intT[],intn){
inti,edge=MaxInt/n/2;
T[0]=1;
if(n!
=0){
for(i=1;iT[i]=T[i-1]*i*2;
if(T[i]>edge)return0;
}
T[n]=T[n-1]*n*2;
}
cout<<"T["<return1;
}
voidmain(){
intA[arraySize];inti;
for(i=0;iif(!
calc(A,i)){
cout<<"failedat"<
break;
}
}
1-9
(1)在下面所给函数的适当地方插入计算count的语句:
voidd(ArrayElementx[],intn){
inti=1;
do{
x[i]+=2;i+=2;
}while(i<=n);
i=1;
while(i<=(n/2)){
x[i]+=x[i+1];i++;
}
}
(2)将由
(1)所得到的程序化简。
使得化简后的程序与化简前的程序具有相同的count值。
(3)程序执行结束时的count值是多少?
(4)使用执行频度的方法计算这个程序的程序步数,画出程序步数统计表。
【解答】
(1)在适当的地方插入计算count语句
voidd(ArrayElementx[],intn){
inti=1;
count++;
do{
x[i]+=2;count++;
i+=2;count++;
count++;//针对while语句
}while(i<=n);
i=1;
count++;
while(i<=(n/2)){
count++;//针对while语句
x[i]+=x[i+1];
count++;
i++;
count++;
}
count++;//针对最后一次while语句
}
(2)将由
(1)所得到的程序化简。
化简后的程序与原来的程序有相同的count值:
voidd(ArrayElementx[],intn){
inti=1;
do{
count+=3;i+=2;
}while(i<=n);
i=1;
while(i<=(n/2)){
count+=3;i++;
}
count+=3;
}
(3)程序执行结束后的count值为3n+3。
当n为偶数时,count=3*(n/2)+3*(n/2)+3=3*n+3
当n为奇数时,count=3*((n+1)/2)+3*((n–1)/2)+3=3*n+3
(4)使用执行频度的方法计算程序的执行步数,画出程序步数统计表:
行号
程序语句
一次执行步数
执行频度
程序步数
1
2
3
4
5
6
7
8
9
10
11
12
voidd(ArrayElementx[],intn){
inti=1;
do{
x[i]+=2;
i+=2;
}while(i<=n);
i=1;
while(i<=(n/2)){
x[i]+=x[i+1];
i++;
}
}
0
1
0
1
1
1
1
1
1
1
0
0
1
1
⎣(n+1)/2⎦
⎣(n+1)/2⎦
⎣(n+1)/2⎦
⎣(n+1)/2⎦
1
⎣n/2+1⎦
⎣n/2⎦
⎣n/2⎦
⎣n/2⎦
1
0
1
0
⎣(n+1)/2⎦
⎣(n+1)/2⎦
⎣(n+1)/2⎦
1
⎣n/2+1⎦
⎣n/2⎦
⎣n/2⎦
0
0
(n≠0)
3n+3
四、其他练习题
1-10填空题
(A)由某一数据对象和该对象中各个数据成员间的关系组成。
依据所有数据成员之间关系的不同,(A)分为两大类:
(B)和(C)。
在(B)中的各个数据成员依次排列在一个线性序列中;(C)的各个数据成员不再保持在一个线性序列中,每个数据成员可能与零个或多个其他数据成员发生联系。
根据视点的不同,数据结构分为数据的(D)和(E)。
(D)是面向问题的,(E)是面向计算机的。
【解答】
A:
数据结构B:
线性结构C:
非线性结构
D:
逻辑结构E:
存储结构
1-11判断下列叙述的对错。
如果正确,在题前打“√”,否则打“⨯”。
(1)数据元素是数据的最小单位。
(2)数据结构是数据对象与对象中数据元素之间关系的集合。
(3)数据结构是具有结构的数据对象。
(4)数据的逻辑结构是指各数据元素之间的逻辑关系,是用户按使用需要建立的。
(5)算法和程序原则上没有区别,在讨论数据结构时二者是通用的。
【解答】
(1)⨯
(2)√(3)⨯(4)√(5)⨯
1-12判断下列叙述的对错。
如果正确,在题前打“√”,否则打“⨯”。
(1)所谓数据的逻辑结构是指数据元素之间的逻辑关系。
(2)同一数据逻辑结构中的所有数据元素都具有相同的特性是指数据元素所包含的数据项的个数都相等。
(3)数据的逻辑结构与数据元素本身的内容和形式无关。
(4)数据结构是指相互之间存在一种或多种关系的数据元素的全体。
(5)从逻辑关系上讲,数据结构主要分为两大类:
线性结构和非线性结构。
【解答】
(1)√
(2)⨯(3)√(4)⨯(5)√
1-13填空题
算法是一个有穷的指令集,它为解决某一特定任务规定了一个运算序列。
它应当具有输入、输出、(A)、有穷性和可执行性等特性。
算法效率的度量分为(B)和(C)。
(B)主要通过在算法的某些部位插装时间函数来测定算法完成某一规定功能所需的时间。
而(C)不实际运行算法,它是分析算法中语句的执行次数来度量算法的时间复杂性。
程序所需的存储空间包含两个部分(D)和(E)。
(D)空间的大小与输入输出数据的个数多少,数值大小无关;(E)空间主要包括其大小与问题规模有关的成分变量所占空间,引用变量所占空间,以及递归栈所用的空间,还有在算法运行过程中动态分配和回收的空间。
【解答】
A:
确定性B:
事后测量C:
事前估计
D:
固定部分E:
可变部分
1-14有下列几种用二元组表示的数据结构,试画出它们分别对应的图形表示(当出现多个关系时,对每个关系画出相应的结构图),并指出它们分别属于何种结构。
(1)A=(K,R),其中
K={a1,a2,a3,a4},R={}
(2)B=(K,R),其中
K={a,b,c,d,e,f,g,h},R={r},
r={,,,,,,}