数据结构课后习题答案[1] 下载本文

第 1 章 绪 论

1. 填空

⑴ 在顺序表中,等概率情况下,插入和删除一个元素平均需移动( )个元素,具体移动元素的个数与( )和( )有关。

【解答】表长的一半,表长,该元素在表中的位置

⑵ 顺序表中第一个元素的存储地址是100,每个元素的长度为2,则第5个元素的存储地址是( )。 【解答】108

【分析】第5个元素的存储地址=第1个元素的存储地址+(5-1)×2=108

⑶ 设单链表中指针p 指向结点A,若要删除A的后继结点(假设A存在后继结点),则需修改指针的操作为( )。

【解答】p->next=(p->next)->next ⑷ 单链表中设置头结点的作用是( )。 【解答】为了运算方便

【分析】例如在插入和删除操作时不必对表头的情况进行特殊处理。

⑸ 非空的单循环链表由头指针head指示,则其尾结点(由指针p所指)满足( )。 【解答】p->next=head 【分析】如图2-8所示。

⑹ 在由尾指针rear指示的单循环链表中,在表尾插入一个结点s的操作序列是( );删除开始结点的操作序列为( )。

【解答】s->next =rear->next; rear->next =s; rear =s;(将S的指针域先弄成表尾指针域,而表尾指针域是代表下个结点的地址信息,所以要将指针域要用S替代,最后把表尾给S) q=rear->next->next; rear->next->next=q->next; delete q; 【分析】操作示意图如图2-9所示:

⑺ 一个具有n个结点的单链表,在指针p所指结点后插入一个新结点的时间复杂度为( );在给定值为x的结点后插入一个新结点的时间复杂度为( )。 【解答】Ο(1),Ο(n)

【分析】在p所指结点后插入一个新结点只需修改指针,所以时间复杂度为Ο(1)(是表示常数计算时间);而在给定值为x的结点后插入一个新结点需要先查找值为x的结点,所以时间复杂度为Ο(n)。 ⑻ 可由一个尾指针唯一确定的链表有( )、( )、( )。 【解答】循环链表,循环双链表,双链表 2. 选择题

⑴ 线性表的顺序存储结构是一种( )的存储结构,线性表的链接存储结构是一种( )的存储结构。 A 随机存取 B 顺序存取 C 索引存取 D 散列存取 【解答】A,B 【分析】参见2.2.1。

⑵ 线性表采用链接存储时,其地址( )。

A 必须是连续的 B 部分地址必须是连续的 C 一定是不连续的 D 连续与否均可以 【解答】D

【分析】线性表的链接存储是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以连续,也可以不连续,甚至可以零散分布在内存中任意位置。 ⑶ 单循环链表的主要优点是( )。 A 不再需要头指针了

B 从表中任一结点出发都能扫描到整个链表;

C 已知某个结点的位置后,能够容易找到它的直接前驱; D 在进行插入、删除操作时,能更好地保证链表不断开。 【解答】B

⑷ 链表不具有的特点是( )。

A 可随机访问任一元素 B 插入、删除不需要移动元素 C 不必事先估计存储空间 D 所需空间与线性表长度成正比 【解答】A

⑸ 若某线性表中最常用的操作是取第i 个元素和找第i个元素的前驱,则采用( )存储方法最节省时间。 A 顺序表 B 单链表 C 双链表 D 单循环链表 【解答】A

【分析】线性表中最常用的操作是取第i 个元素,所以,应选择随机存取结构即顺序表,同时在顺序表中查找第i个元素的前驱也很方便。单链表和单循环链表既不能实现随机存取,查找第i个元素的前驱也不方便,双链表虽然能快速查找第i个元素的前驱,但不能实现随机存取。

⑹ 若链表中最常用的操作是在最后一个结点之后插入一个结点和删除第一个结点,则采用( )存储方法最节省时间。

A 单链表 B 带头指针的单循环链表 C 双链表 D 带尾指针的单循环链表 【解答】D

【分析】在链表中的最后一个结点之后插入一个结点需要知道终端结点的地址,所以,单链表、带头指针的单循环链表、双链表都不合适,考虑在带尾指针的单循环链表中删除第一个结点,其时间性能是O(1),所以,答案是D 。

⑺ 若链表中最常用的操作是在最后一个结点之后插入一个结点和删除最后一个结点,则采用( )存储方法最节省运算时间。

A 单链表 B 循环双链表 C单循环链表 D 带尾指针的单循环链表 【解答】B

【分析】在链表中的最后一个结点之后插入一个结点需要知道终端结点的地址,所以,单链表、单循环链表都不合适,删除最后一个结点需要知道终端结点的前驱结点的地址,所以,带尾指针的单循环链表不合适,而循环双链表满足条件。

⑻ 在具有n个结点的有序单链表中插入一个新结点并仍然有序的时间复杂度是( )。 A O(1) B O(n) C O(n2) D O(nlog2n) 【解答】B

【分析】首先应顺序查找新结点在单链表中的位置。

⑼ 对于n个元素组成的线性表,建立一个有序单链表的时间复杂度是( )。 A O(1) B O(n) C O(n2) D O(nlog2n) 【解答】C

【分析】该算法需要将n个元素依次插入到有序单链表中,而插入每个元素需O(n)。 ⑽ 使用双链表存储线性表,其优点是可以( )。 A 提高查找速度 B 更方便数据的插入和删除 C 节约存储空间 D 很快回收存储空间 【解答】B

【分析】在链表中一般只能进行顺序查找,所以,双链表并不能提高查找速度,因为双链表中有两个指针域,显然不能节约存储空间,对于动态存储分配,回收存储空间的速度是一样的。由于双链表具有对称性,所以,其插入和删除操作更加方便。

⑾ 在一个单链表中,已知q所指结点是p所指结点的直接前驱,若在q和p之间插入s所指结点,则执行( )操作。

A s->next=p->next; p->next=s; B q->next=s; s->next=p; C p->next=s->next; s->next=p; D p->next=s; s->next=q; 【解答】B

【分析】注意此题是在q和p之间插入新结点,所以,不用考虑修改指针的顺序。 ⑿ 在循环双链表的p所指结点后插入s所指结点的操作是( )。 A p->next=s; s->prior=p; p->next->prior=s; s->next=p->next; B p->next=s; p->next->prior=s; s->prior=p; s->next=p->next; C s->prior=p; s->next=p->next; p->next=s; p->next->prior=s; D s->prior=p; s->next=p->next; p->next->prior=s; p->next=s 【解答】D

【分析】在链表中,对指针的修改必须保持线性表的逻辑关系,否则,将违背线性表的逻辑特征,图2-10给出备选答案C和D的图解。

3. 判断题

⑴ 线性表的逻辑顺序和存储顺序总是一致的。

【解答】错。顺序表的逻辑顺序和存储顺序一致,链表的逻辑顺序和存储顺序不一定一致。 ⑵ 线性表的顺序存储结构优于链接存储结构。 【解答】错。两种存储结构各有优缺点。 ⑶ 设p,q是指针,若p=q,则*p=*q。

【解答】错。p=q只能表示p和q指向同一起始地址,而所指类型则不一定相同。 ⑷ 线性结构的基本特征是:每个元素有且仅有一个直接前驱和一个直接后继。

【解答】错。每个元素最多只有一个直接前驱和一个直接后继,第一个元素没有前驱,最后一个元素没有后继。

⑸ 在单链表中,要取得某个元素,只要知道该元素所在结点的地址即可,因此单链表是随机存取结构。 【解答】错。要找到该结点的地址,必须从头指针开始查找,所以单链表是顺序存取结构。 4.请说明顺序表和单链表各有何优缺点,并分析下列情况下,采用何种存储结构更好些。

⑴ 若线性表的总长度基本稳定,且很少进行插入和删除操作,但要求以最快的速度存取线性表中的元素。 ⑵ 如果n个线性表同时并存,并且在处理过程中各表的长度会动态发生变化。 ⑶ 描述一个城市的设计和规划。

【解答】顺序表的优点:① 无需为表示表中元素之间的逻辑关系而增加额外的存储空间;② 可以快速地存取表中任一位置的元素(即随机存取)。顺序表的缺点:① 插入和删除操作需移动大量元素;② 表的容量难以确定;③ 造成存储空间的“碎片”。

单链表的优点:① 不必事先知道线性表的长度;② 插入和删除元素时只需修改指针,不用移动元素。单链表的缺点:① 指针的结构性开销;② 存取表中任意元素不方便,只能进行顺序存取。

⑴ 应选用顺序存储结构。因为顺序表是随机存取结构,单链表是顺序存取结构。本题很少进行插入和删除操作,所以空间变化不大,且需要快速存取,所以应选用顺序存储结构。

⑵ 应选用链接存储结构。链表容易实现表容量的扩充,适合表的长度动态发生变化。

⑶ 应选用链接存储结构。因为一个城市的设计和规划涉及活动很多,需要经常修改、扩充和删除各种信息,才能适应不断发展的需要。而顺序表的插入、删除的效率低,故不合适。 5.算法设计

⑴ 设计一个时间复杂度为O(n)的算法,实现将数组A[n]中所有元素循环右移k个位置。 【解答】算法思想请参见主教材第一章思想火花。下面给出具体算法。

分析算法,第一次调用Reverse函数的时间复杂度为O(k),第二次调用Reverse函数的时间复杂度为O(n-k),第三次调用Reverse函数的时间复杂度为O(n),所以,总的时间复杂度为O(n)。

⑵ 已知数组A[n]中的元素为整型,设计算法将其调整为左右两部分,左边所有元素为奇数,右边所有元素为偶数,并要求算法的时间复杂度为O(n)。

【解答】从数组的两端向中间比较,设置两个变量i和j,初始时i=0,j=n-1,若A[i]为偶数并且A[j]为奇数,则将A[i]与A[j]交换。具体算法如下:

分析算法,两层循环将数组扫描一遍,所以,时间复杂度为O(n)。

⑶ 试编写在无头结点的单链表上实现线性表的插入操作的算法,并和带头结点的单链表上的插入操作的实现进行比较。 【解答】参见2.2.3。

⑷ 试分别以顺序表和单链表作存储结构,各写一实现线性表就地逆置的算法。

【解答】顺序表的逆置,即是将对称元素交换,设顺序表的长度为length,则将表中第i个元素与第length-i-1个元素相交换。具体算法如下:

单链表的逆置请参见2.2.4算法2-4和算法2-6。

⑸ 假设在长度大于1的循环链表中,即无头结点也无头指针,s为指向链表中某个结点的指针,试编写算法删除结点s的前驱结点。

【解答】利用单循环链表的特点,通过指针s可找到其前驱结点r以及r的前驱结点p,然后将结点r删除,如图2-11所示,具体算法如下:

⑹ 已知一单链表中的数据元素含有三类字符:字母、数字和其他字符。试编写算法,构造三个循环链表,使每个循环链表中只含同一类字符。

【解答】在单链表A中依次取元素,若取出的元素是字母,把它插入到字母链表B 中,若取出的元素是数字,则把它插入到数字链表D中,直到链表的尾部,这样表B,D,A中分别存放字母、数字和其他字符。具体算法如下:

⑺ 设单链表以非递减有序排列,设计算法实现在单链表中删去值相同的多余结点。

【解答】从头到尾扫描单链表,若当前结点的元素值与后继结点的元素值不相等,则指针后移;否则删除该后继结点。具体算法如下:

⑻ 判断带头结点的双循环链表是否对称。

【解答】设工作指针p和q分别指向循环双链表的开始结点和终端结点,若结点p和结点q的数据域相等,则工作指针p后移,工作指针q前移,直到指针p和指针q指向同一结点(循环双链表中结点个数为奇数),或结点q成为结点p的前驱(循环双链表中结点个数为偶数)。如图2-12所示。

学习自测及答案

1. 已知一维数组A采用顺序存储结构,每个元素占用4个存储单元,第9个元素的地址为144,则第一个元素的地址是( )。 A 108 B 180 C 176 D 112 【解答】D

2.在长度为n的线性表中查找值为x的数据元素的时间复杂度为: ( )。 A O(0) B O(1) C O(n) D O(n2) 【解答】C

3.在一个长度为n的顺序表的第i(1≤i≤n+1)个元素之前插入一个元素,需向后移动( )个元素,删除第i(1≤i≤n)个元素时,需向前移动( )个元素。 【解答】n-i+1,n-i

4.在单链表中,除了头结点以外,任一结点的存储位置由( )指示。 【解答】其前驱结点的指针域

5.当线性表采用顺序存储结构时,其主要特点是( )。 【解答】逻辑结构中相邻的结点在存储结构中仍相邻

6.在双链表中,每个结点设置了两个指针域,其中一个指向( )结点,另一个指向( )结点。 【解答】前驱,后继

7.设A是一个线性表(a1, a2, …, an),采用顺序存储结构,则在等概率的前提下,平均每插入一个元素

需要移动的元素个数为多少?若元素插在ai与ai+1之间(1≤i≤n)的概率为插入一个元素所要移动的元素个数又是多少? 【解答】

,则平均每

8.线性表存放在整型数组A[arrsize]的前elenum 个单元中,且递增有序。编写算法,将元素x插入到线性表的适当位置上,以保持线性表的有序性,并且分析算法的时间复杂度。

【解答】本题是在一个递增有序表中插入元素x,基本思路是从有序表的尾部开始依次取元素与x比较,若大于x,此元素后移一位,再取它前面一个元素重复上述步骤;否则,找到插入位置,将x插入。具体算法如下:

9. 已知单链表中各结点的元素值为整型且递增有序,设计算法删除链表中所有大于mink且小于maxk的所有元素,并释放被删结点的存储空间。

【解答】因为是在有序单链表上的操作,所以,要充分利用其有序性。在单链表中查找第一个大于mink的结点和第一个小于maxk的结点,再将二者间的所有结点删除。

10.设单循环链表L1,对其遍历的结果是:x1, x2, x3,…, xn-1, xn。请将该循环链表拆成两个单循环链表L1和L2,使得L1中含有原L1表中序号为奇数的结点且遍历结果为:x1, x3,… ;L2中含有原L1表中序号为偶数的结点且遍历结果为:… , x4, x2。 【解答】算法如下:

第 3 章 特殊线性表——栈、队列和串

课后习题讲解 1. 填空

⑴ 设有一个空栈,栈顶指针为1000H,现有输入序列为1、2、3、4、5, 经过push,push,pop,push,pop,push,push后,输出序列是( ),栈顶指针为( )。 【解答】23,1003H

⑵ 栈通常采用的两种存储结构是( );其判定栈空的条件分别是( ),判定栈满的条件分别是( )。 【解答】顺序存储结构和链接存储结构(或顺序栈和链栈),栈顶指针top= -1和top=NULL,栈顶指针top等于数组的长度和内存无可用空间

⑶( )可作为实现递归函数调用的一种数据结构。 【解答】栈

【分析】递归函数的调用和返回正好符合后进先出性。 ⑷ 表达式a*(b+c)-d的后缀表达式是( )。 【解答】abc+*d-

【分析】将中缀表达式变为后缀表达式有一个技巧:将操作数依次写下来,再将算符插在它的两个操作数的后面。

⑸ 栈和队列是两种特殊的线性表,栈的操作特性是( ),队列的操作特性是( ),栈和队列的主要区别在于( )。

【解答】后进先出,先进先出,对插入和删除操作限定的位置不同 ⑹ 循环队列的引入是为了克服( )。 【解答】假溢出

⑺ 数组Q[n]用来表示一个循环队列,front为队头元素的前一个位置,rear为队尾元素的位置,计算队列中元素个数的公式为( )。 【解答】(rear-front+n)% n

【分析】也可以是(rear-front)% n,但rear-front的结果可能是负整数,而对一个负整数求模,其结果在不同的编译器环境下可能会有所不同。

⑻ 用循环链表表示的队列长度为n,若只设头指针,则出队和入队的时间复杂度分别是( )和( )。 【解答】O(1),O(n)

【分析】在带头指针的循环链表中,出队即是删除开始结点,这只需修改相应指针;入队即是在终端结点的后面插入一个结点,这需要从头指针开始查找终端结点的地址。 ⑼ 串是一种特殊的线性表,其特殊性体现在( )。 【解答】数据元素的类型是一个字符 ⑽ 两个串相等的充分必要条件是( )。 【解答】长度相同且对应位置的字符相等 【分析】例如\,\。 2. 选择题

⑴ 若一个栈的输入序列是1,2,3,…,n,输出序列的第一个元素是n,则第i个输出元素是( )。 A 不确定 B n-i C n-i-1 D n-i+1 【解答】D

【分析】此时,输出序列一定是输入序列的逆序。

⑵ 设栈S和队列Q的初始状态为空,元素e1、e2、e3、e4、e5、e6依次通过栈S,一个元素出栈后即进入队列Q,若6个元素出队的顺序是e2、e4、e3、e6、e5、e1,则栈S的容量至少应该是( )。 A 6 B 4 C 3 D 2 【解答】C

【分析】由于队列具有先进先出性,所以,此题中队列形同虚设,即出栈的顺序也是e2、e4、e3、e6、e5、e1。

⑶ 一个栈的入栈序列是1,2,3,4,5,则栈的不可能的输出序列是( )。 A 54321 B 45321 C 43512 D 12345 【解答】C

【分析】此题有一个技巧:在输出序列中任意元素后面不能出现比该元素小并且是升序(指的是元素的序号)的两个元素。

⑷ 设计一个判别表达式中左右括号是否配对的算法,采用( )数据结构最佳 A 顺序表 B 栈 C 队列 D 链表 【解答】B

【分析】每个右括号与它前面的最后一个没有匹配的左括号配对,因此具有后进先出性。

⑸ 在解决计算机主机与打印机之间速度不匹配问题时通常设置一个打印缓冲区,该缓冲区应该是一个( )结构。

A 栈 B队列 C 数组 D线性表 【解答】B

【分析】先进入打印缓冲区的文件先被打印,因此具有先进先出性。 ⑹ 一个队列的入队顺序是1,2,3,4,则队列的输出顺序是( )。 A 4321 B 1234 C 1432 D 3241 【解答】B

【分析】队列的入队顺序和出队顺序总是一致的。 ⑺ 栈和队列的主要区别在于( )。

A 它们的逻辑结构不一样 B 它们的存储结构不一样 C 所包含的运算不一样 D 插入、删除运算的限定不一样 【解答】D

【分析】栈和队列的逻辑结构都是线性的,都有顺序存储和链接存储,有可能包含的运算不一样,但不是主要区别,任何数据结构在针对具体问题时包含的运算都可能不同。

⑻ 设数组S[n]作为两个栈S1和S2的存储空间,对任何一个栈只有当S[n]全满时才不能进行进栈操作。为这两个栈分配空间的最佳方案是( )。 A S1的栈底位置为0,S2的栈底位置为n-1 B S1的栈底位置为0,S2的栈底位置为n/2 C S1的栈底位置为0,S2的栈底位置为n D S1的栈底位置为0,S2的栈底位置为1 【解答】A

【分析】两栈共享空间首先两个栈是相向增长的,栈底应该分别指向两个栈中的第一个元素的位置,并注意C++中的数组下标是从0开始的。

⑼ 设有两个串p和q,求q在p中首次出现的位置的运算称作( )。 A 连接 B 模式匹配 C 求子串 D 求串长 【解答】B 3. 判断题

⑴ 有n个元素依次进栈,则出栈序列有(n-1)/2种。

【解答】错。应该有 种。

⑵ 栈可以作为实现过程调用的一种数据结构。

【解答】对。只要操作满足后进先出性,都可以采用栈作为辅助数据结构。 ⑶ 在栈满的情况下不能做进栈操作,否则将产生―上溢‖。 【解答】对。

⑷ 在循环队列中,front指向队头元素的前一个位置,rear指向队尾元素的位置,则队满的条件是front=rear。

【解答】错。这是队空的判定条件,在循环队列中要将队空和队满的判定条件区别开。 ⑸ 空串与空格串是相同的。

【解答】错。空串的长度为零,而空格串的长度不为0,其长度是串中空格的个数。

4. 设有一个栈,元素进栈的次序为A,B,C,D,E,能否得到如下出栈序列,若能,请写出操作序列,若不能,请说明原因。 ⑴ C,E,A,B,D ⑵ C,B,A,D,E

【解答】⑴不能,因为在C、E出栈的情况下,A一定在栈中,而且在B的下面,不可能先于B出栈。⑵可以,设I为进栈操作,O为入栈操作,则其操作序列为IIIOOOIOIO。 5. 举例说明顺序队列的―假溢出‖现象。

【解答】假设有一个顺序队列,如图3-6所示,队尾指针rear=4,队头指针front=1,如果再有元素入队,就会产生―上溢‖,此时的―上溢‖又称为―假溢出‖,因为队列并不是真的溢出了,存储队列的数组中还有2个存储单元空闲,其下标分别为0和1。

6. 在操作序列push(1)、push(2)、pop、push(5)、push(7)、pop、push(6)之后,栈顶元素和栈底元素分别是什么?(push(k)表示整数k入栈,pop表示栈顶元素出栈。) 【解答】栈顶元素为6,栈底元素为1。其执行过程如图3-7所示。

7. 在操作序列EnQueue(1)、 EnQueue(3)、 DeQueue、EnQueue(5)、EnQueue(7)、DeQueue、EnQueue(9)之后,队头元素和队尾元素分别是什么?(EnQueue(k)表示整数k入队,DeQueue表示队头元素出队)。 【解答】队头元素为5,队尾元素为9。其执行过程如图3-8所示。

8.空串和空格串有何区别?串中的空格符有何意义?空串在串处理中有何作用?

【解答】不含任何字符的串称为空串,其长度为零。仅含空格的串称为空格串,它的长度为串中空格符的个数。串中的空格符可用来分隔一般的字符,便于人们识别和阅读,但计算串长时应包括这些空格符。空串在串处理中可作为任意串的子串。 9. 算法设计

⑴ 假设以不带头结点的循环链表表示队列,并且只设一个指针指向队尾结点,但不设头指针。试设计相应的入队和出队的算法。

【解答】出队操作是在循环链表的头部进行,相当于删除开始结点,而入队操作是在循环链表的尾部进行,相当于在终端结点之后插入一个结点。由于循环链表不带头结点,需要处理空表的特殊情况。 入队算法如下:

出队算法如下:

⑵ 设顺序栈S中有2n个元素,从栈顶到栈底的元素依次为a2n,a2n-1,…,a1,要求通过一个循环队列重新排列栈中元素,使得从栈顶到栈底的元素依次为a2n,a2n-2,…,a2,a2n-1,a2n-3,…,a1,请设计算法实现该操作,要求空间复杂度和时间复杂度均为O(n)。 【解答】操作步骤为: ① 将所有元素出栈并入队;

② 依次将队列元素出队,如果是偶数结点,则再入队,如果是奇数结点,则入栈; ③ 将奇数结点出栈并入队; ④ 将偶数结点出队并入栈; ⑤ 将所有元素出栈并入队; ⑥ 将所有元素出队并入栈即为所求。

⑶ 用顺序存储结构存储串S,编写算法删除S中第 i个字符开始的连续j个字符。

【解答】先判断串S中要删除的内容是否存在,若存在,则将第i+j-1之后的字符前移j个位置。算法如下:

⑷ 对于采用顺序存储结构的串S,编写一个函数删除其值等于ch的所有字符。

【解答】从后向前删除值为ch的所有元素,这样所有移动的元素中没有值为ch的元素,能减少移动元素的次数,提高算法的效率。算法如下:

⑸ 对串的模式匹配KMP算法设计求模式滑动位置的next函数。 【解答】参见3.2.5 学习自测及答案

1.在一个具有n个单元的顺序栈中,假定以地址低端(即下标为0的单元)作为栈底,以top作为栈顶指针,当出栈时,top的变化为( )。 A 不变 B top=0; C top=top-1; D top=top+1; 【解答】C

2.一个栈的入栈序列是a, b, c, d, e,则栈的不可能的出栈序列是( )。 A edcba B cdeba C debca D abcde 【解答】C

3.从栈顶指针为top的链栈中删除一个结点,用x保存被删除结点的值,则执行( )。 A x=top; top=top->next; B x=top->data;

C top=top->next; x=top->data; D x=top->data; top=top->next; 【解答】D

4.设元素1, 2, 3, P, A依次经过一个栈,进栈次序为123PA,在栈的输出序列中,有哪些序列可作为C++程序设计语言的变量名。

【解答】PA321, P3A21, P32A1, P321A, AP321 5.设S=\,其长度为( )。 【解答】15

第 4 章 广义线性表——多维数组和广义表

课后习题讲解 1. 填空

⑴ 数组通常只有两种运算:( )和( ),这决定了数组通常采用( )结构来实现存储。 【解答】存取,修改,顺序存储

【分析】数组是一个具有固定格式和数量的数据集合,在数组上一般不能做插入、删除元素的操作。除了初始化和销毁之外,在数组中通常只有存取和修改两种操作。

⑵ 二维数组A中行下标从10到20,列下标从5到10,按行优先存储,每个元素占4个存储单元,A[10][5]的存储地址是1000,则元素A[15][10]的存储地址是( )。 【解答】1140

【分析】数组A中每行共有6个元素,元素A[15][10]的前面共存储了(15-10)×6+5个元素,每个元素占4个存储单元,所以,其存储地址是1000+140=1140。

⑶ 设有一个10阶的对称矩阵A采用压缩存储,A[0][0]为第一个元素,其存储地址为d,每个元素占1个存储单元,则元素A[8][5]的存储地址为( )。 【解答】d+41

【分析】元素A[8][5]的前面共存储了(1+2+…+8)+5=41个元素。 ⑷ 稀疏矩阵一般压缩存储方法有两种,分别是( )和( )。 【解答】三元组顺序表,十字链表

⑸ 广义表((a), (((b),c)),(d))的长度是( ),深度是( ),表头是( ),表尾是( )。 【解答】3,4,(a),((((b),c)),(d))

⑹ 已知广义表LS=(a,(b,c,d),e),用Head和Tail函数取出LS中原子b的运算是( )。 【解答】Head(Head(Tail(LS))) 2. 选择题

⑴ 二维数组A的每个元素是由6个字符组成的串,行下标的范围从0~8,列下标的范围是从0~9,则存放A至少需要( )个字节,A的第8列和第5行共占( )个字节,若A按行优先方式存储,元素A[8][5]的起始地址与当A按列优先方式存储时的( )元素的起始地址一致。 A 90 B 180 C 240 D 540 E 108 F 114 G 54 H A[8][5] I A[3][10] J A[5][8] K A[4][9] 【解答】D,E,K

【分析】数组A为9行10列,共有90个元素,所以,存放A至少需要90×6=540个存储单元,第8列和第5行共有18个元素(注意行列有一个交叉元素),所以,共占108个字节,元素A[8][5]按行优先存储的起始地址为d+8×10+5=d+85,设元素A[i][j]按列优先存储的起始地址与之相同,则d+j×9+i=d+85,解此方程,得i=4,j=9。

⑵ 将数组称为随机存取结构是因为( )

A 数组元素是随机的 B 对数组任一元素的存取时间是相等的 C 随时可以对数组进行访问 D 数组的存储结构是不定 【解答】B

⑶ 下面的说法中,不正确的是( )

A 数组是一种线性结构 B 数组是一种定长的线性结构

C 除了插入与删除操作外,数组的基本操作还有存取、修改、检索和排序等 D 数组的基本操作有存取、修改、检索和排序等,没有插入与删除操 【解答】C

【分析】数组属于广义线性表,数组被创建以后,其维数和每维中的元素个数是确定的,所以,数组通常没有插入和删除操作。

⑷ 对特殊矩阵采用压缩存储的目的主要是为了( ) A 表达变得简单 B 对矩阵元素的存取变得简单 C 去掉矩阵中的多余元素 D 减少不必要的存储空间 【解答】D

【分析】在特殊矩阵中,有很多值相同的元素并且他们的分布有规律,没有必要为值相同的元素重复存储。 ⑸ 下面( )不属于特殊矩阵。

A 对角矩阵 B 三角矩阵 C 稀疏矩阵 D 对称矩阵 【解答】C

⑹ 若广义表A满足Head(A)=Tail(A),则A为( ) A ( ) B (( )) C (( ),( )) D(( ),( ),( )) 【解答】B

⑺ 下面的说法中,不正确的是( )

A 广义表是一种多层次的结构 B 广义表是一种非线性结构 C 广义表是一种共享结构 D 广义表是一种递归 【解答】B

【分析】从各层元素各自具有的线性关系讲,广义表属于线性结构。 ⑻ 下面的说法中,不正确的是( )

A 对称矩阵只须存放包括主对角线元素在内的下(或上)三角的元素即可。 B 对角矩阵只须存放非零元素即可。

C 稀疏矩阵中值为零的元素较多,因此可以采用三元组表方法存储。

D 稀疏矩阵中大量值为零的元素分布有规律,因此可以采用三元组表方法存储 【解答】D

【分析】稀疏矩阵中大量值为零的元素分布没有规律,因此采用三元组表存储。如果零元素的分布有规律,就没有必要存储非零元素的行号和列号,而需要按其压缩规律找出相应的映象函数。 3. 判断题

⑴ 数组是一种复杂的数据结构,数组元素之间的关系既不是线性的,也不是树形的。 【解答】错。例如二维数组可以看成是数据元素为线性表的线性表。 ⑵ 使用三元组表存储稀疏矩阵的元素,有时并不能节省存储空间。

【解答】对。因为三元组表除了存储非零元素值外,还需要存储其行号和列号。 ⑶ 稀疏矩阵压缩存储后,必会失去随机存取功能。

【解答】对。因为压缩存储后,非零元素的存储位置和行号、列号之间失去了确定的关系。

⑷ 线性表可以看成是广义表的特例,如果广义表中的每个元素都是单元素,则广义表便成为线性表。 【解答】对。

⑸ 若一个广义表的表头为空表,则此广义表亦为空表。

【解答】错。如广义表L=(( ),(a,b))的表头为空表,但L不是空表。

4.一个稀疏矩阵如图4-4所示,写出对应的三元组顺序表和十字链表存储表示。

【解答】对应的三元组顺序表如图4-5所示,十字链表如图4-6所示。

5.已知A为稀疏矩阵,试从空间和时间角度比较采用二维数组和三元组顺序表两种不同的存储结构完成求 运算的优缺点。

【解答】设稀疏矩阵为m行n列,如果采用二维数组存储,其空间复杂度为O(m×n);因为要将所有的矩阵元素累加起来,所以,需要用一个两层的嵌套循环,其时间复杂度亦为O(m×n)。如果采用三元组顺序表进行压缩存储,假设矩阵中有t个非零元素,其空间复杂度为O(t),将所有的矩阵元素累加起来只需将三元组顺序表扫描一遍,其时间复杂度亦为O(t)。当t << m×n时,采用三元组顺序表存储可获得较好的时、空性能。

6.设某单位职工工资表ST由―工资‖、―扣除‖和―实发金额‖三项组成,其中工资项包括―基本工资‖、―津贴‖和―奖金‖,扣除项包括―水‖、―电‖和―煤气‖ 。

⑴ 请用广义表形式表示所描述的工资表ST,并用表头和表尾求表中的―奖金‖项; ⑵ 画出该工资表ST的存储结构。

【解答】⑴ ST=((基本工资,津贴,奖金),(水,电,煤气),实发金额) Head(Tail(Tail(Head(ST))))=奖金

⑵ 工资表ST的头尾表示法如图4-7所示。

7.若在矩阵A中存在一个元素ai,j(0≤i≤n-1,0≤j≤m-1),该元素是第i行元素中最小值且又是第j列元素中最大值,则称此元素为该矩阵的一个马鞍点。假设以二维数组存储矩阵A,试设计一个求该矩阵所有马鞍点的算法,并分析最坏情况下的时间复杂度。

【解答】在矩阵中逐行寻找该行中的最小值,然后对其所在的列寻找最大值,如果该列上的最大值与该行上的最小值相等,则说明该元素是鞍点,将它所在行号和列号输出。

具体算法如下:

分析算法,外层for循环共执行n次,内层第一个for循环执行m次,第二个for循环最坏情况下执行n次,所以,最坏情况下的时间复杂度为O(mn+n2)。 学习自测及答案 (没看)

1.二维数组M中每个元素的长度是3个字节,行下标从0到7,列下标从0到9,从首地址d开始存储。若按行优先方式存储,元素M[7][5]的起始地址为( ),若按列优先方式存储,元素M[7][5]的起始地址为( )。 【解答】d+22,d+141

2.一个n×n的对称矩阵,按行优先或列优先进行压缩存储,则其存储容量为( )。 【解答】n(n+1)/2

3.设n行n列的下三角矩阵A(行列下标均从1开始)已压缩到一维数组S[1]~S[n(n+1)/2]中,若按行优先存储,则A[i][j]在数组S中的存储位置是( )。 【解答】i×(i-1)/2+j

4.已知广义表LS=(a, (b, c), (d, e, a)),运用Head函数和Tail函数取出LS中原子d的运算是( )。 【解答】Head(Head(Tail(Tail(LS)))) 5.广义表(a, b, (c, (d)))的表尾是( )。 A (d) B (c,(d)) C b,(c,(d)) D (b,(c,(d))) 【解答】D

6.设有三对角矩阵An×n(行、列下标均从0开始),将其三条对角线上的元素逐行存于数组B[3n-2]中,使得B[k]=aij求:

⑴ 用i, j表示k的下标变换公式; ⑵ 用k表示i, j的下标变换公式。

【解答】⑴ 要求i, j表示k的下标变换公式,就是要求在k之前已经存储了多少个非零元素,这些非零元素的个数就是k的值。元素aij求所在的行为i,列为j,则在其前面的非零元素的个数是;k=2 + 3(i-1)+( j-i + 1)= 2i+ j。

⑵ 因为k和i, j之间是一一对应的关系,k+1是当前非零元素的个数,整除即为其所在行号,取余表示当前行中第几个非零元素,加上前面零元素所在列数就是当前列号,即:

7.已知两个n×n的对称矩阵按压缩存储方法存储在已维数组A和B中,编写算法计算对称矩阵的乘积。 【解答】对称矩阵采用压缩存储,乘积矩阵也采用压缩存储。注意矩阵元素的表示方法。

第 5 章 树和二叉树

课后习题讲解

1. 填空题

⑴ 树是n(n≥0)结点的有限集合,在一棵非空树中,有( )个根结点,其余的结点分成m(m>0)个( )的集合,每个集合都是根结点的子树。 【解答】有且仅有一个,互不相交

⑵ 树中某结点的子树的个数称为该结点的( ),子树的根结点称为该结点的( ),该结点称为其子树根结点的( )。

【解答】度,孩子,双亲

⑶ 一棵二叉树的第i(i≥1)层最多有( )个结点;一棵有n(n>0)个结点的满二叉树共有( )个叶子结点和( )个非终端结点。 【解答】2i-1,(n+1)/2,(n-1)/2

【分析】设满二叉树中叶子结点的个数为n0,度为2的结点个数为n2,由于满二叉树中不存在度为1的结点,所以n=n0+n2;由二叉树的性质n0=n2+1,得n0=(n+1)/2,n2=(n-1)/2。

⑷ 设高度为h的二叉树上只有度为0和度为2的结点,该二叉树的结点数可能达到的最大值是( ),最小值是( )。 【解答】2h -1,2h-1

【分析】最小结点个数的情况是第1层有1个结点,其他层上都只有2个结点。

⑸ 深度为k的二叉树中,所含叶子的个数最多为( )。 【解答】2k-1

【分析】在满二叉树中叶子结点的个数达到最多。

⑹ 具有100个结点的完全二叉树的叶子结点数为( )。 【解答】50

【分析】100个结点的完全二叉树中最后一个结点的编号为100,其双亲即最后一个分支结点的编号为50,也就是说,从编号51开始均为叶子。

⑺ 已知一棵度为3的树有2个度为1的结点,3个度为2的结点,4个度为3的结点。则该树中有( )个叶子结点。 【解答】12

【分析】根据二叉树性质3的证明过程,有n0=n2+2n3+1(n0、n2、n3分别为叶子结点、度为2的结点和度为3的结点的个数)。

⑻ 某二叉树的前序遍历序列是ABCDEFG,中序遍历序列是CBDAFGE,则其后序遍历序列是( )。 【解答】CDBGFEA

【分析】根据前序遍历序列和后序遍历序列将该二叉树构造出来。

⑼ 在具有n个结点的二叉链表中,共有( )个指针域,其中( )个指针域用于指向其左右孩子,剩下的( )个指针域则是空的。 【解答】2n,n-1,n+1

⑽ 在有n个叶子的哈夫曼树中,叶子结点总数为( ),分支结点总数为( )。 【解答】n,n-1

【分析】n-1个分支结点是经过n-1次合并后得到的。

2. 选择题

⑴ 如果结点A有3个兄弟,B是A的双亲,则结点B的度是( )。 A 1 B 2 C 3 D 4 【解答】D

⑵ 设二叉树有n个结点,则其深度为( )。 A n-1 B n C 【解答】D

【分析】此题并没有指明是完全二叉树,则其深度最多是n,最少是

+1。

+1 D 不能确定

⑶ 二叉树的前序序列和后序序列正好相反,则该二叉树一定是( )的二叉树。 A 空或只有一个结点 B 高度等于其结点数 C 任一结点无左孩子 D 任一结点无右孩子 【解答】B

【分析】此题注意是序列正好相反,则左斜树和右斜树均满足条件。

⑷ 线索二叉树中某结点R没有左孩子的充要条件是( )。 A R.lchild=NULL B R.ltag=0 C R.ltag=1 D R.rchild=NULL 【解答】C

【分析】线索二叉树中某结点是否有左孩子,不能通过左指针域是否为空来判断,而要判断左标志是否为1。

⑸ 深度为k的完全二叉树至少有( )个结点,至多有( )个结点,具有n个结点的完全二叉树按层序从1开始编号,则编号最小的叶子的序号是( )。 A 2k-2+1 B 2k-1 C 2k -1 D 2k–1 -1 E 2k+1 F 2k+1 -1 G 2k -1+1 H 2k 【解答】B,C,A

【分析】深度为k的完全二叉树最少结点数的情况应是第k层上只有1个结点,最多的情况是满二叉树,编号最小的叶子应该是在结点数最少的情况下,叶子结点的编号。

⑹ 一个高度为h的满二叉树共有n个结点,其中有m个叶子结点,则有( )成立。 A n=h+m B h+m=2n C m=h-1 D n=2m-1 【解答】D

【分析】满二叉树中没有度为1的结点,所以有m个叶子结点,则度为2的结点个数为m-1。

⑺ 任何一棵二叉树的叶子结点在前序、中序、后序遍历序列中的相对次序( )。 A 肯定不发生改变 B 肯定发生改变 C 不能确定 D 有时发生变化 【解答】A

【分析】三种遍历次序均是先左子树后右子树。

⑻ 如果T' 是由有序树T转换而来的二叉树,那么T中结点的前序序列就是T' 中结点的( )序列,T中结点的后序序列就是 T' 中结点的( )序列。 A 前序 B 中序 C 后序 D 层序 【解答】A,B

⑼ 设森林中有4棵树,树中结点的个数依次为n1、n2、n3、n4,则把森林转换成二叉树后,其根结点的右子树上有( )个结点,根结点的左子树上有( )个结点。 A n1-1 B n1 C n1+n2+n3 D n2+n3+n4 【解答】D,A

【分析】由森林转换的二叉树中,根结点即为第一棵树的根结点,根结点的左子树是由第一棵树中除了根结点以外其余结点组成的,根结点的右子树是由森林中除第一棵树外其他树转换来的。

⑽ 讨论树、森林和二叉树的关系,目的是为了( )。 A 借助二叉树上的运算方法去实现对树的一些运算

B 将树、森林按二叉树的存储方式进行存储并利用二叉树的算法解决树的有关问题 C 将树、森林转换成二叉树

D 体现一种技巧,没有什么实际意义 【解答】B 3. 判断题

⑴ 在线索二叉树中,任一结点均有指向其前驱和后继的线索。

【解答】错。某结点是否有前驱或后继的线索,取决于该结点的标志域是否为1。

⑵ 在二叉树的前序遍历序列中,任意一个结点均处在其子女的前面。 【解答】对。由前序遍历的操作定义可知。

⑶ 二叉树是度为2的树。

【解答】错。二叉树和树是两种不同的树结构,例如,左斜树是一棵二叉树,但它的度为1。

⑷ 由树转换成二叉树,其根结点的右子树总是空的。 【解答】对。因为根结点无兄弟结点。

⑸ 用一维数组存储二叉树时,总是以前序遍历存储结点。

【解答】错。二叉树的顺序存储结构是按层序存储的,一般适合存储完全二叉树。

4.证明:对任一满二叉树,其分枝数B=2(n0-1) 。(其中,n0为终端结点数) 【解答】因为在满二叉树中没有度为1的结点,所以有: n=n0+n2

设B为树中分枝数,则 n=B+1 所以 B=n0 +n2-1 再由二叉树性质: n0=n2+1 代入上式有:

B=n0+n0-1-1=2(n0-1)

5.证明:已知一棵二叉树的前序序列和中序序列,则可唯一确定该二叉树。 【解答】证明采用归纳法。

设二叉树的前序遍历序列为a1a2a3… an,中序遍历序列为b1b2b3… bn。

当n=1时,前序遍历序列为a1,中序遍历序列为b1,二叉树只有一个根结点,所以,a1= b1,可以唯一确定该二叉树;

假设当n<=k时,前序遍历序列a1a2a3… ak和中序遍历序列b1b2b3… bk可唯一确定该二叉树,下面证明当n=k+1时,前序遍历序列a1a2a3… akak+1和中序遍历序列b1b2b3… bk bk+1可唯一确定一棵二叉树。

在前序遍历序列中第一个访问的一定是根结点,即二叉树的根结点是a1,在中序遍历序列中查找值为a1的结点,假设为bi,则a1=bi且b1b2… bi-1是对根结点a1的左子树进行中序遍历的结果,前序遍历序列a2a3… ai是对根结点a1的左子树进行前序遍历的结果,由归纳假设,前序遍历序列a2a3… ai和中序遍历序列b1b2… bi-1唯一确定了根结点的左子树,同样可证前序遍历序列ai+1ai+2… ak+1和中序遍历序列bi+1bi+2… bk+1唯一确定了根结点的右子树。

6.已知一棵度为m的树中有:n1个度为1的结点,n2个度为2的结点,……,nm个度为m的结点,问该树中共有多少个叶子结点? 【解答】设该树的总结点数为n,则 n=n0+n1+n2+……+nm 又:

n=分枝数+1=0×n0+1×n1+2×n2+……+m×nm+1 由上述两式可得:

n0= n2+2n3+……+(m-1)nm+1

7.已知二叉树的中序和后序序列分别为CBEDAFIGH和CEDBIFHGA,试构造该二叉树。 【解答】二叉树的构造过程如图5-12 所示。

8.对给定的一组权值W=(5,2,9,11,8,3,7),试构造相应的哈夫曼树,并计算它的带权路径长度。

【解答】构造的哈夫曼树如图5-13所示。

树的带权路径长度为:

WPL=2×4+3×4+5×3+7×3+8×3+9×2+11×2 =120

9.已知某字符串S中共有8种字符,各种字符分别出现2次、1次、4次、5次、7次、3次、4次和9次,对该字符串用[0,1]进行前缀编码,问该字符串的编码至少有多少位。

【解答】以各字符出现的次数作为叶子结点的权值构造的哈夫曼编码树如图5-14所示。其带权路径长度=2×5+1×5+3×4+5×3+9×2+4×3+4×3+7×2=98,所以,该字符串的编码长度至少为98位。

10.算法设计

⑴ 设计算法求二叉树的结点个数。

【解答】本算法不是要打印每个结点的值,而是求出结点的个数。所以可将遍历算法中的―访问‖操作改为―计数操作‖,将结点的数目累加到一个全局变量中,每个结点累加一次即完成了结点个数的求解。 具体算法如下:

⑵ 设计算法按前序次序打印二叉树中的叶子结点。

【解答】本算法的要求与前序遍历算法既有相同之处,又有不同之处。相同之处是打印次序均为前序,不同之处是此处不是打印每个结点的值,而是打印出其中的叶子结点,即为有条件打印。为此,将前序遍历算法中的访问操作改为条件打印即可。算法如下:

⑶ 设计算法求二叉树的深度。

【解答】当二叉树为空时,深度为0;若二叉树不为空,深度应是其左右子树深度的最大值加1,而其左右子树深度的求解又可通过递归调用本算法来完成。具体算法如下:

⑷ 编写算法,要求输出二叉树后序遍历序列的逆序。

【解答】要想得到后序的逆序,只要按照后序遍历相反的顺序即可,即先访问根结点,再遍历根结点的右子树,最后遍历根结点的左子树。注意和前序遍历的区别,具体算法如下:

⑸ 以二叉链表为存储结构,编写算法求二叉树中结点x的双亲。

【解答】对二叉链表进行遍历,在遍历的过程中查找结点x并记载其双亲。具体算法如下:

⑹ 以二叉链表为存储结构,在二叉树中删除以值x为根结点的子树。

【解答】对二叉链表进行遍历,在遍历的过程中查找结点x并记载其双亲,然后将结点x的双亲结点中指向结点x的指针置空。具体算法如下:

⑺ 一棵具有n个结点的二叉树采用顺序存储结构,编写算法对该二叉树进行前序遍历。 【解答】按照题目要求,设置一个工作栈以完成对该树的非递归算法,思路如下:

① 每访问一个结点,将此结点压栈,查看此结点是否有左子树,若有,访问左子树,重复执行该过程直到左子树为空。

② 从栈弹出一个结点,如果此结点有右子树,访问右子树执行步骤①,否则重复执行步骤②。 具体算法如下:

⑻ 编写算法交换二叉树中所有结点的左右子树。

【解答】对二叉树进行后序遍历,在遍历过程中访问某结点时交换该结点的左右子树。 具体算法如下:

⑼ 以孩子兄弟表示法做存储结构,求树中结点x的第i个孩子。

【解答】先在链表中进行遍历,在遍历过程中查找值等于x的结点,然后由此结点的最左孩子域firstchild找到值为x结点的第一个孩子,再沿右兄弟域rightsib找到值为x结点的第i个孩子并返回指向这个孩子的指针。

树的孩子兄弟表示法中的结点结构定义如下: template struct TNode { T data;

TNode *firstchild, *rightsib; };

具体算法如下:

学习自测及答案

1.前序遍历和中序遍历结果相同的二叉树是( )。 A 根结点无左孩子的二叉树 B 根结点无右孩子的二叉树

C 所有结点只有左子树的二叉树 D 所有结点只有右子树的二叉树 【解答】D

1.前序遍历和中序遍历结果相同的二叉树是( )。 A 根结点无左孩子的二叉树 B 根结点无右孩子的二叉树 C 所有结点只有左子树的二叉树 D 所有结点只有右子树的二叉树【解答】D

2.由权值为{3, 8, 6, 2, 5}的叶子结点生成一棵哈夫曼树,其带权路径长度为( )。 A 24 B 48 C 53 D 72 【解答】C

3.用顺序存储的方法将完全二叉树中的所有结点逐层存放在数组A[1] ~ A[n]中,结点A[i]若有左子树,则左子树的根结点是( )。

A A[2i-1] B A[2i+1] C A[i/2] D A[2i] 【解答】D

4.对任何一棵二叉树T,如果其终端结点的个数为n0,度为2的结点个数为n2,则( )。 A n0=n2-1 B n0=n2 C n0=n2+1 D 没有规律 【解答】C

5.一棵满二叉树中共有n个结点,其中有m个叶子结点,深度为h,则( )。 A n=h+m B h+m=2n C m=h-1 D n=2h-1 【解答】D

6.对于完全二叉树中的任一结点,若其右分支下的子孙的最大层次为h,则其左分支下的子孙的最大层次为( )。

A h B h+1 C h或h+1 D 任意 【解答】C

7.假定一棵度为3的树中结点数为50,则其最小高度应为 。 A 3 B 4 C 5 D 6 【解答】C

8.在线索二叉树中,一个结点是叶子结点的充要条件为( )。 A 左线索标志为0,右线索标志为1 B 左线索标志为1,右线索标志为0 C 左、右线索标志均为0 D 左、右线索标志均为1 【解答】C

9.对于一棵具有n个结点的树,其所有结点的度之和为( )。 【解答】n-1

10.在顺序存储的二叉树中,编号为i和j的两个结点处在同一层的条件是( )。 【解答】

11.现有按前序遍历二叉树的结果ABC,问有哪几种不同的二叉树可以得到这一结果? 【解答】共有5种二叉树可以得到这一结果,如图5-15所示。

12.试找出分别满足下列条件的所有二叉树: ⑴ 前序序列和中序序列相同。 ⑵ 中序序列和后序序列相同。 ⑶ 前序序列和后序序列相同。

【解答】 ⑴ 空二叉树、只有一个根结点的二叉树和右斜树。 ⑵ 空二叉树、只有一个根结点的二叉树和左斜树。 ⑶ 空二叉树、只有一个根结点的二叉树

13.将下面图5-16所示的树转换为二叉树,图5-17所示的二叉树转换为树或森林。

【解答】图5-16所示树转换的二叉树如图5-18所示,图5-17所示二叉树转换的森林如图5-19所示。

14.以孩子兄弟表示法作为存储结构,编写算法求树的深度。

【解答】采用递归算法实现。若树为空树,则其深度为0,否则其深度等于第一棵子树的深度+1和兄弟子树的深度中的较大者。具体算法如下:

15.设计算法,判断一棵二叉树是否为完全二叉树。

【解答】根据完全二叉树的定义可知,对完全二叉树按照从上到下、从左到右的次序(即层序)遍历应该满足:

⑴ 若某结点没有左孩子,则其一定没有右孩子; ⑵ 若某结点无右孩子,则其所有后继结点一定无孩子。

若有一结点不满足其中任意一条,则该二叉树就一定不是完全二叉树。因此可采用按层次遍历二叉树的方法依次对每个结点进行判断是否满足上述两个条件。为此,需设两个标志变量BJ和CM,其中BJ表示已扫描过的结点是否均有左右孩子,CM存放局部判断结果及最后的结果。 具体算法如下:

第 6 章 图

课后习题讲解 1. 填空题

⑴ 设无向图G中顶点数为n,则图G至少有( )条边,至多有( )条边;若G为有向图,则至少有( )条边,至多有( )条边。 【解答】0,n(n-1)/2,0,n(n-1)

【分析】图的顶点集合是有穷非空的,而边集可以是空集;边数达到最多的图称为完全图,在完全图中,任意两个顶点之间都存在边。

⑵ 任何连通图的连通分量只有一个,即是( )。 【解答】其自身

⑶ 图的存储结构主要有两种,分别是( )和( )。 【解答】邻接矩阵,邻接表

【分析】这是最常用的两种存储结构,此外,还有十字链表、邻接多重表、边集数组等。 ⑷ 已知无向图G的顶点数为n,边数为e,其邻接表表示的空间复杂度为( )。 【解答】O(n+e)

【分析】在无向图的邻接表中,顶点表有n个结点,边表有2e个结点,共有n+2e个结点,其空间复杂度为O(n+2e)=O(n+e)。

⑸ 已知一个有向图的邻接矩阵表示,计算第j个顶点的入度的方法是( )。 【解答】求第j列的所有元素之和

⑹ 有向图G用邻接矩阵A[n][n]存储,其第i行的所有元素之和等于顶点i的( )。 【解答】出度

⑺ 图的深度优先遍历类似于树的( )遍历,它所用到的数据结构是( );图的广度优先遍历类似于树的( )遍历,它所用到的数据结构是( )。 【解答】前序,栈,层序,队列

⑻ 对于含有n个顶点e条边的连通图,利用Prim算法求最小生成树的时间复杂度为( ),利用Kruskal算法求最小生成树的时间复杂度为( )。 【解答】O(n2),O(elog2e)

【分析】Prim算法采用邻接矩阵做存储结构,适合于求稠密图的最小生成树;Kruskal算法采用边集数组做存储结构,适合于求稀疏图的最小生成树。

⑼ 如果一个有向图不存在( ),则该图的全部顶点可以排列成一个拓扑序列。 【解答】回路

⑽ 在一个有向图中,若存在弧、、,则在其拓扑序列中,顶点vi, vj, vk的相对次序为( )。 【解答】vi, vj, vk

【分析】对由顶点vi, vj, vk组成的图进行拓扑排序。 2. 选择题

⑴ 在一个无向图中,所有顶点的度数之和等于所有边数的( )倍。 A 1/2 B 1 C 2 D 4 【解答】C

【分析】设无向图中含有n个顶点e条边,则 。

⑵ n个顶点的强连通图至少有( )条边,其形状是( )。 A n B n+1 C n-1 D n×(n-1)

E 无回路 F 有回路 G 环状 H 树状 【解答】A,G

⑶ 含n 个顶点的连通图中的任意一条简单路径,其长度不可能超过( )。 A 1 B n/2 C n-1 D n 【解答】C

【分析】若超过n-1,则路径中必存在重复的顶点。

⑷ 对于一个具有n个顶点的无向图,若采用邻接矩阵存储,则该矩阵的大小是( )。 A n B (n-1)2 C n-1 D n2 【解答】D

⑸ 图的生成树( ),n个顶点的生成树有( )条边。 A 唯一 B 不唯一 C 唯一性不能确定 D n E n +1 F n-1 【解答】C,F

⑹ 设无向图G=(V, E)和G' =(V', E' ),如果G' 是G的生成树,则下面的说法中错误的是( )。 A G' 为 G的子图 B G' 为 G的连通分量

C G' 为G的极小连通子图且V = V' D G' 是G的一个无环子图 【解答】B

【分析】连通分量是无向图的极大连通子图,其中极大的含义是将依附于连通分量中顶点的所有边都加上,所以,连通分量中可能存在回路。

⑺ G是一个非连通无向图,共有28条边,则该图至少有( )个顶点。 A 6 B 7 C 8 D 9 【解答】D

【分析】n个顶点的无向图中,边数e≤n(n-1)/2,将e=28代入,有n≥8,现已知无向图非连通,则n=9。 ⑻ 最小生成树指的是( ) 。 A 由连通网所得到的边数最少的生成树 B 由连通网所得到的顶点数相对较少的生成树 C 连通网中所有生成树中权值之和为最小的生成树 D 连通网的极小连通子图

⑼ 判定一个有向图是否存在回路除了可以利用拓扑排序方法外,还可以用( )。 A 求关键路径的方法 B 求最短路径的方法 C 广度优先遍历算法 D 深度优先遍历算法 【解答】D

【分析】当有向图中无回路时,从某顶点出发进行深度优先遍历时,出栈的顺序(退出DFSTraverse算法)即为逆向的拓扑序列。

⑽ 下面关于工程计划的AOE网的叙述中,不正确的是( )?br /> A 关键活动不按期完成就会影响整个工程的完成时间

B 任何一个关键活动提前完成,那么整个工程将会提前完成 C 所有的关键活动都提前完成,那么整个工程将会提前完成 D 某些关键活动若提前完成,那么整个工程将会提前完 【解答】B

【分析】AOE网中的关键路径可能不止一条,如果某一个关键活动提前完成,还不能提前整个工程,而必须同时提高在几条关键路径上的关键活动。 3. 判断题

⑴ 一个有向图的邻接表和逆邻接表中的结点个数一定相等。

【解答】对。邻接表和逆邻接表的区别仅在于出边和入边,边表中的结点个数都等于有向图中边的个数。 ⑵ 用邻接矩阵存储图,所占用的存储空间大小只与图中顶点个数有关,而与图的边数无关。 【解答】对。邻接矩阵的空间复杂度为O(n2),与边的个数无关。 ⑶ 图G的生成树是该图的一个极小连通子图 【解答】错。必须包含全部顶点。

⑷ 无向图的邻接矩阵一定是对称的,有向图的邻接矩阵一定是不对称的

【解答】错。有向图的邻接矩阵不一定对称,例如有向完全图的邻接矩阵就是对称的。 ⑸ 对任意一个图,从某顶点出发进行一次深度优先或广度优先遍历,可访问图的所有顶点。 【解答】错。只有连通图从某顶点出发进行一次遍历,可访问图的所有顶点。 ⑹ 在一个有向图的拓扑序列中,若顶点a在顶点b之前,则图中必有一条弧。 【解答】错。只能说明从顶点a到顶点b有一条路径。

⑺ 若一个有向图的邻接矩阵中对角线以下元素均为零,则该图的拓扑序列必定存在。 【解答】对。参见第11题的证明。

⑻ 在AOE网中一定只有一条关键路径?br />【解答】错。AOE网中可能有不止一条关键路径,他们的路径长度相同。

4.n个顶点的无向图,采用邻接表存储,回答下列问题?br />⑴ 图中有多少条边? ⑵ 任意两个顶点i和j是否有边相连? ⑶ 任意一个顶点的度是多少?br />【解答】

⑴ 边表中的结点个数之和除以2。 ⑵ 第i个边表中是否含有结点j。 ⑶ 该顶点所对应的边表中所含结点个数。

5.n个顶点的无向图,采用邻接矩阵存储,回答下列问题: ⑴ 图中有多少条边?

⑵ 任意两个顶点i和j是否有边相连? ⑶ 任意一个顶点的度是多少? 【解答】

⑴ 邻接矩阵中非零元素个数的总和除以2。

⑵ 当邻接矩阵A中A[i][j]=1(或A[j][i]=1)时,表示两顶点之间有边相连。 ⑶ 计算邻接矩阵上该顶点对应的行上非零元素的个数。 6.证明:生成树中最长路径的起点和终点的度均为1。 【解答】用反证法证明。

设v1, v2, …, vk是生成树的一条最长路径,其中,v1为起点,vk为终点。若vk的度为2,取vk的另一个邻接点v,由于生成树中无回路,所以,v在最长路径上,显然v1, v2, …, vk , v的路径最长,与假设矛盾。所以生成树中最长路径的终点的度为1。 同理可证起点v1的度不能大于1,只能为1。

7.已知一个连通图如图6-6所示,试给出图的邻接矩阵和邻接表存储示意图,若从顶点v1出发对该图进行遍历,分别给出一个按深度优先遍历和广度优先遍历的顶点序列。

【解答】邻接矩阵表示如下:

深度优先遍历序列为:v1 v2 v3 v5 v4 v6 广度优先遍历序列为:v1 v2 v4 v6 v3 v5 邻接表表示如下:

8.图6-7所示是一个无向带权图,请分别按Prim算法和Kruskal算法求最小生成树。

【解答】按Prim算法求最小生成树的过程如下:

按Kruskal算法求最小生成树的过程如下:

9.对于图6-8所示的带权有向图,求从源点v1到其他各顶点的最短路径。

【解答】从源点v1到其他各顶点的最短路径如下表所示。 源点 终点 最短路径 最短路径长度 v1 v7 v1 v7 7 v1 v5 v1 v5 11 v1 v4 v1 v7 v4 13 v1 v6 v1 v7 v4 v6 16 v1 v2 v1 v7 v2 22 v1 v3 v1 v7 v4 v6 v3 25

10.如图6-9所示的有向网图,利用Dijkstra算法求从顶点v1到其他各顶点的最短路径。

【解答】从源点v1到其他各顶点的最短路径如下表所示。 源点 终点 最短路径 最短路径长度 v1 v3 v1 v3 15 v1 v5 v1 v5 15 v1 v2 v1 v3 v2 25 v1 v6 v1 v3 v2 v6 40 v1 v4 v1 v3 v2 v4 45

11.证明:只要适当地排列顶点的次序,就能使有向无环图的邻接矩阵中主对角线以下的元素全部为0。 【解答】任意n个结点的有向无环图都可以得到一个拓扑序列。设拓扑序列为v0v1v2…vn-1,我们来证明此时的邻接矩阵A为上三角矩阵。证明采用反证法。

假设此时的邻接矩阵不是上三角矩阵,那么,存在下标i和j(i>j),使得A[i][j]不等于零,即图中存在从vi到vj的一条有向边。由拓扑序列的定义可知,在任意拓扑序列中,vi的位置一定在vj之前,而在上述拓扑序列v0v1v2…vn-1中,由于i>j,即vi的位置在vj之后,导致矛盾。因此命题正确。 12. 算法设计

⑴ 设计算法,将一个无向图的邻接矩阵转换为邻接表。

【解答】先设置一个空的邻接表,然后在邻接矩阵上查找值不为零的元素,找到后在邻接表的对应单链表中插入相应的边表结点。 邻接矩阵存储结构定义如下: const int MaxSize=10; template struct AdjMatrix {

T vertex[MaxSize]; //存放图中顶点的数组 int arc[MaxSize][MaxSize]; //存放图中边的数组 int vertexNum, arcNum; //图的顶点数和边数 };

邻接表存储结构定义如下:

const int MaxSize=10; struct ArcNode //定义边表结点 {

int adjvex; //邻接点域 ArcNode *next; }; template

struct VertexNode //定义顶点表结点 { T vertex;

ArcNode *firstedge; };

struct AdjList {

VertexNode adjlist[MaxSize];

int vertexNum, arcNum; //图的顶点数和边数 };

具体算法如下:

⑵ 设计算法,将一个无向图的邻接表转换成邻接矩阵。

【解答】在邻接表上顺序地取每个边表中的结点,将邻接矩阵中对应单元的值置为1。邻接矩阵和邻接表的存储结构定义与上题相同。具体算法如下:

⑶ 设计算法,计算图中出度为零的顶点个数。

【解答】在有向图的邻接矩阵中,一行对应一个顶点,每行的非零元素的个数等于对应顶点的出度。因此,当某行非零元素的个数为零时,则对应顶点的出度为零。据此,从第一行开始,查找每行的非零元素个数是否为零,若是则计数器加1。具体算法如下:

⑷ 以邻接表作存储结构,设计按深度优先遍历图的非递归算法。 【解答】参见6.2.1。

⑸ 已知一个有向图的邻接表,编写算法建立其逆邻接表。

【解答】在有向图中,若邻接表中顶点vi有邻接点vj,在逆邻接表中vj一定有邻接点vi,由此得到本题算法思路:首先将逆邻接表的表头结点firstedge域置空,然后逐行将表头结点的邻接点进行转化。

⑹ 分别基于深度优先搜索和广度优先搜索编写算法,判断以邻接表存储的有向图中是否存在由顶点vi到顶点vj的路径(i≠j)。 【解答】⑴ 基于深度优先遍历:

⑵ 基于广度优先遍历:

学习自测及答案

1.某无向图的邻接矩阵A=A 3 B 6 C 9 D 以上答案均不正确 【解答】A

,可以看出,该图共有( )个顶点。

2.无向图的邻接矩阵是一个( ),有向图的邻接矩阵是一个( ) A 上三角矩阵 B 下三角矩阵 C 对称矩阵 D 无规律 【解答】C,D

3.下列命题正确的是( )。

A 一个图的邻接矩阵表示是唯一的,邻接表表示也唯一 B 一个图的邻接矩阵表示是唯一的,邻接表表示不唯一 C 一个图的邻接矩阵表示不唯一的,邻接表表示是唯一 D 一个图的邻接矩阵表示不唯一的,邻接表表示也不唯一 【解答】B

4.十字链表适合存储( ),邻接多重表适合存储( )。 【解答】有向图,无向图

5. 在一个具有n 个顶点的有向完全图中包含有( )条边: A n(n-1)/2 B n(n-1) C n(n+1)/2 D n2 【解答】B

6.n个顶点的连通图用邻接矩阵表示时,该矩阵至少有( )个非零元素。 【解答】2(n-1)

7.表示一个有100个顶点,1000条边的有向图的邻接矩阵有( )个非零矩阵元素。 【解答】1000

8.一个具有n个顶点k条边的无向图是一个森林(n>k),则该森林中必有( )棵树。 A k B n C n - k D 1 【解答】C

9.用深度优先遍历方法遍历一个有向无环图,并在深度优先遍历算法中按退栈次序打印出相应的顶点,则输出的顶点序列是( )。

A 逆拓扑有序 B 拓扑有序 C 无序 D 深度优先遍历序列 【解答】A

10. 关键路径是AOE网中( )。

A 从源点到终点的最长路径 B从源点到终点的最长路径 C 最长的回路 D 最短的回路 【解答】A

11. 已知无向图G的邻接表如图6-10所示,分别写出从顶点1出发的深度遍历和广度遍历序列,并画出相应的生成树。

【解答】深度优先遍历序列为:1,2,3,4,5,6 对应的生成树为:

广度优先遍历序列为:1,2,4,3,5,6 对应的生成树为:

12. 已知已个AOV网如图6-11所示,写出所有拓扑序列。

【解答】拓扑序列为:v0 v1 v5 v2 v3 v6 v4、 v0 v1 v5 v2 v6 v3 v4、 v0 v1 v5 v6 v2 v3 v4。

第 7 章 查找技术

课后习题讲解

1. 填空题

⑴ 顺序查找技术适合于存储结构为( )的线性表,而折半查找技术适用于存储结构为( )的线性表,并且表中的元素必须是( )。

【解答】顺序存储和链接存储,顺序存储,按关键码有序

⑵ 设有一个已按各元素值排好序的线性表,长度为125,用折半查找与给定值相等的元素,若查找成功,则至少需要比较( )次,至多需比较( )次。 【解答】1,7

【分析】在折半查找判定树中,查找成功的情况下,和根结点的比较次数最少,为1次,最多不超过判定树的深度。

⑶ 对于数列{25,30,8,5,1,27,24,10,20,21,9,28,7,13,15},假定每个结点的查找概率相同,若用顺序存储结构组织该数列,则查找一个数的平均比较次数为( )。若按二叉排序树组织该数列,则查找一个数的平均比较次数为( )。 【解答】8,59/15

【分析】根据数列将二叉排序树画出,将二叉排序树中查找每个结点的比较次数之和除以数列中的元素个数,即为二叉排序树的平均查找长度。

⑷ 长度为20的有序表采用折半查找,共有( )个元素的查找长度为3。

【解答】4

【分析】在折半查找判定树中,第3层共有4个结点。

⑸ 假定一个数列{25,43,62,31,48,56},采用的散列函数为H(k)=k mod 7,则元素48的同义词是( )。 【解答】62

【分析】H(48)= H(62)=6

⑹ 在散列技术中,处理冲突的两种主要方法是( )和( )。 【解答】开放定址法,拉链法

⑺ 在各种查找方法中,平均查找长度与结点个数无关的查找方法是( )。 【解答】散列查找

【分析】散列表的平均查找长度是装填因子的函数,而不是记录个数n的函数。

⑻ 与其他方法相比,散列查找法的特点是( )。

【解答】通过关键码计算记录的存储地址,并进行一定的比较 2. 选择题

⑴ 静态查找与动态查找的根本区别在于( )。

A 它们的逻辑结构不一样 B 施加在其上的操作不同 C 所包含的数据元素的类型不一样 D 存储实现不一样 【解答】B

【分析】静态查找不涉及插入和删除操作,而动态查找涉及插入和删除操作。

⑵ 有一个按元素值排好序的顺序表(长度大于2),分别用顺序查找和折半查找与给定值相等的元素,比较次数分别是s和b,在查找成功的情况下,s和b的关系是( );在查找不成功的情况下,s和b的关系是( )。

A s=b B s>b C s 【解答】D,D

【分析】此题没有指明是平均性能。例如,在有序表中查找最大元素,则顺序查找比折半查找快,而平均性能折半查找要优于顺序查找,查找不成功的情况也类似。

⑶ 长度为 12的有序表采用顺序存储结构,采用折半查找技术,在等概率情况下,查找成功时的平均查找长度是( ),查找失败时的平均查找长度是( )。 A 37/12 B 62/13 C 3 9/12 D 49/13 【解答】A,B

【分析】画出长度为12的折半查找判定树,判定树中有12个内结点和13个外结点。

⑷ 用n个键值构造一棵二叉排序树,其最低高度为( )。 A n/2 B n C log2n D log2n+1 【解答】D

【分析】二叉排序树的最低高度与完全二叉树的高度相同。

⑸ 二叉排序树中,最小值结点的( )。 A 左指针一定为空 B 右指针一定为空 C 左、右指针均为空 D 左、右指针均不为空 【解答】A

【分析】在二叉排序树中,值最小的结点一定是中序遍历序列中第一个被访问的结点,即二叉树的最左下结点。

⑹ 散列技术中的冲突指的是( )。

A 两个元素具有相同的序号 B 两个元素的键值不同,而其他属性相同 C 数据元素过多 D 不同键值的元素对应于相同的存储地址 【解答】D

⑺ 设散列表表长m=14,散列函数H(k)=k mod 11。表中已有15、38、61、84四个元素,如果用线性探侧法处理冲突,则元素49的存储地址是( )。 A 8 B 3 C 5 D 9 【解答】A

【分析】元素15、38、61、84分别存储在4、5、6、7单元,而元素49的散列地址为5,发生冲突,向后探测3个单元,其存储地址为8。

⑻ 在采用线性探测法处理冲突所构成的闭散列表上进行查找,可能要探测多个位置,在查 找成功的情况下,所探测的这些位置的键值( )。

A 一定都是同义词 B 一定都不是同义词 C不一定都是同义词 D 都相同 【解答】C

【分析】采用线性探测法处理冲突会产生堆积,即非同义词争夺同一个后继地址。

3. 判断题

⑴ 二叉排序树的充要条件是任一结点的值均大于其左孩子的值,小于其右孩子的值。 【解答】错。

分析二叉排序树的定义,是左子树上的所有结点的值都小于根结点的值,右子树上的所有结点的值都大于根结点的值。例如图7-7所示二叉树满足任一结点的值均大于其左孩子的值,小于其右孩子的值,但不是二叉排序树。