数据结构(C语言版 第2版严蔚敏)课后全部习题答案(完整版)
目录
第一章 绪论
1. 简述下列术语:数据、数据元素、数据对象、数据结构、存储结构、数据类型和抽象数据类型
【解答】
(1)数据:是客观事物的符号表示,是所有能输入到计算机中并被计算机程序处理的符号的总称。
(2)数据元素:是数据的基本单位,在计算机中通常作为一个整体进行考虑和处理。
(3)数据项:是组成数据元素的、有独立含义的、不可分割的最小单位。例如,学生基本信息表中的学号、姓名、性别等都是数据项。
(4)数据对象:是性质相同的数据元素的集合,是数据的一个子集。
(5)数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。
(6)逻辑结构:从逻辑关系上描述数据,它与数据的存储无关,是独立于计算机的。因此,数据的逻辑结构可以看作是从具体问题抽象出来的数学模型。
(7)存储结构:数据对象在计算机中的存储表示,也称为物理结构。
(8)抽象数据类型:由用户定义的,表示应用问题的数学模型,以及定义在这个模型上的一组操作的总称。具体包括三部分:数据对象、数据对象上关系的集合和对数据对象的基本操作的集合。
2. 试举一个数据结构的例子,叙述其逻辑结构和存储结构两方面的含义和相互关系。
【解答】
如一张学生信息表,其基本信息包括有学生的学号、姓名、性别、籍贯、专业等等。每个学生基本信息记录对应一个数据元素,学生记录按顺序号排列,形成了学生基本信息记录的线性序列。将这些学生记录在计算机中的存储表示就是存储结构。如果用连续的存储单元来存放这些记录,则称为顺序存储结构;如果存储单元不连续,而是随机存放各个记录,然后用指针进行链接,则称为链式存储结构。
即相同的逻辑结构,可以对应不同的存储结构。
3. 简述逻辑结构的四种基本关系并画出它们的关系图。
【解答】
(1)集合结构
数据元素之间除了“属于同一集合”的关系外,别无其他关系。
(2)线性结构
数据元素之间存在一对一的关系。
(3)树结构
数据元素之间存在一对多的关系。
(4)图结构或网状结构
数据元素之间存在多对多的关系。
其中树结构和图结构都属于非线性结构。
4. 存储结构由哪两种基本的存储方法实现?
【解答】
(1)顺序存储结构
顺序存储结构是借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系,通常借助程序设计语言的数组类型来描述。
(2)链式存储结构
顺序存储结构要求所有的元素依次存放在一片连续的存储空间中,而链式存储结构,无需占用一整块存储空间。但为了表示结点之间的关系,需要给每个结点附加指针字段,用于存放后继元素的存储地址。所以链式存储结构通常借助于程序设计语言的指针类型来描述。
5. 选择题
(1)在数据结构中,从逻辑上可以把数据结构分成( )。
A. 动态结构和静态结构 B. 紧凑结构和非紧凑结构
C. 线性结构和非线性结构 D. 内部结构和外部结构
【解答】C
(2)与数据元素本身的形式、内容、相对位置、个数无关的是数据的( )。
A. 存储结构 B. 存储实现
C. 逻辑结构 D. 运算实现
【解答】C
(3)通常要求同一逻辑结构中的所有数据元素具有相同的特性,这意味着( )。
A. 数据具有同一特点
B. 不仅数据元素所包含的数据项的个数要相同,而且对应数据项的类型要一致
C. 每个数据元素都一样
D. 数据元素所包含的数据项的个数要相等
【解答】B
(4)以下说法正确的是( )。
A. 数据元素是数据的最小单位
B. 数据项是数据的基本单位
C. 数据结构是带有结构的各数据项的集合
D. 一些表面上很不相同的数据可以有相同的逻辑结构
【解答】D
数据元素使数据的基本单位。
数据项是组成数据元素的最小单位。
数据结构是带有结构的数据元素的集合。
(5)算法的时间复杂度取决于( )。
A. 问题的规模
B. 待处理数据的初态
C. 计算机的配置
D. A 和 B
【解答】D
(6)以下数据结构中,( )是非线性数据结构。
A. 树 B. 字符串 C. 队列 D. 栈
【解答】A
6. 试分析下列各算法的时间复杂度。
(1)
x = 90; y = 100; while(y > 0) if(x > 100) {x = x - 10; y--;} else x++; 【解答】O(1)
该算法的执行时间不随问题规模 n 的增长而增长。
(2)
for(i = 0; i < n; i++) for(j = 0; j < m; j++) a[i][j] = 0; 【解答】O(nm)
(3)
s = 0; for(i = 0; i < n; i++) for(j = 0; j < n; j++) s += B[i][j]; sum = s; 【解答】
(4)
i = 1; while(i <= n) i = i * 3; 【解答】
设循环体内基本语句的频度为f(n),所以,所以,故时间复杂度为。
i = i * 3,所以 i 的取值都有:1、3、9、27......,相当于 。
(5)
x = 0; for(i = 1; i < n; i++) for(j = 1; j <= n - i; j++) x++; 【解答】
当 i = 1 的时候,内层运行了 (n - 1) 次,
当 i = 2 的时候,内层运行了 (n - 2) 次,
当 i = 3 的时候,内层运行了 (n - 3) 次,
.......
当 i = n - 1(i != n)的时候,内层运行了(n - (n - 1)) 次
所以加起来就是 (n - 1) + (n - 2) + (n - 3) +.....+ 1 = (n - 1 + 1)(n - 1)/2 =故时间复杂度为.
(6)
x = n; //n > 1 y = 0; while(x >= (y + 1) * (y + 1)) y ++; 【解答】
假设语句“y++”的执行次数为 f(n),所以,又x = n,所以,得出,故时间复杂度为.
第二章 线性表
1. 选择题
(1)顺序表中第一个元素的存储地址是100,每 个元素的长度为2,则第5个元素的地址是( )。
A. 110 B. 108 C. 100 D. 120
【解答】 B
顺序表中的数据连续存储,LOC() = LOC() + (i - 1) * l
所以第 5 个元素的地址为: 100 + (5 -1) * 2= 108 。
(2)在n个节点的顺序表中,算法的时间复杂度是 O(1) 的操作是( )。
A. 访问第 i 个节点(
)和求第 i 个节点的直接前驱(
)
B. 在第 i 个节点后插入一个新节点(
)
C. 删除第 i 个节点(
)
D. 将 n 个节点从小到大排序
【解答】 A
顺序表是一种随机存取结构,访问第 i 个节点和求第 i 个节点的直接前驱都可以直接通过数组的下标直接定位,时间复杂度是 O(1) 。在顺序表中插入和删除一个节点的时间复杂度都是,排序的时间复杂度为或。。
(3)向一个有 127 个元素的顺序表中插入一个新元素并保持原来顺序不变, 平均要移动的元素个数为( )。
A. 8 B. 63.5 C. 63 D. 7
【解答】B
平均要移动约表中一半的元素 。
(4)链接存储的存储结构所占存储空间( )。
A. 分两部分,一部分存放节点值,另一部分存放表示节点间关系的指针
B. 只有一部分,存放节点值
C. 只有一部分,存储表示节点间关系的指针
D. 分两部分,一部分存放节点值,另一部分存放节点所占单元数
【解答】A
(5)线性表若采用链式存储结构时,要求内存中可用存储单元的地址( )。
A. 必须是连续的 B. 部分地址必须是连续的
C. 一定是不连续的 D. 连续或不连续都可以
【解答】D
(6)线性表L在( )情况下适用于使用链式结构实现。
A. 需经常修改L中的节点值 B. 需不断对L进行删除插入
C. L中含有大量的节点 D. L中结点结构复杂
【解答】B
链表的插入或删除操作无须移动数据,只需要直接修改指针。
(7)单链表的存储密度( )。
A. 大于 1 B. 等于 1 C. 小于 1 D. 不能确定
【解答】C
链表的存储密度小于1,顺序表的存储密度等于1。
(8)将两个各有 n 个元素的有序表归并成一个有序表,其最少的比较次数是( )。
A. n B. 2n-1 C. 2n D. n-1
【解答】A
假设这两个有序表对应的数组为 A[0, 1,...., n-1],B[0,1....., n-1],且假设A中数据都比B中的小,那么比较的顺序就为A中的元素从第一个开始依次与B中的第一个元素比较,即A[0] < B[0], A[1] < B[0], A[2] < B[0], ......., A[n-1] < B[0],所以比较的次数应该是n次。
比如 表A(1, 2, 3) 与 表B(4, 5, 6) 合并,则1, 2, 3依次与4比较,比较3次然后合并。
(9)在一个长度为 n 的顺序表中,在第 i 个元素(
)之前插入一个新元素时
须向后移动( )个元素。
A. n - i B. n - i + 1 C. n - i - 1 D. i
【解答】B
(10)线性表
,下列说法正确的是( )。
A. 每个元素都有一个直接前驱和一个直接后继
B. 线性表中至少有一个元素
C. 表中诸元素的排列必须是由小到大或由大到小
D. 除第一个和最后一个元素外,其余每个元素都有一个且仅有一个直接前驱和直接后继
【解答】D
A、第一个数据元素没有直接前驱,最后一个数据元素没有直接后继
B、线性表可以为空
C、线性表没有要求顺序
(11)创建一个包括 n 个节点的有序单链表的时间复杂度是( )。
A. O(1) B. O(n) C. O(
) D. O(
)
【解答】C
可以理解成将n个元素依次插入到空链表中,每一个元素插入需要遍历之前已经有序的链表,找到合适的位置,复杂度是O(n)。一共有n个元素,所以就是O()。
单链表创建的时间复杂度是 O(n) ,而要建立一个有序的单链表,则每生成一个新节点时需要和已有的节点进行比较,确定合适的插入位置,这里也是O(n),所以时间复杂度是O() 。
(12)以下说法错误的是( )。
A. 求表长、定位这两种运算在采用顺序存储结构时实现的效率不比采用链式存储结构时实现的效率低
B. 顺序存储的线性表可以随机存取
C. 由于顺序存储要求连续的存储区域,所以在存储管理上不够灵活
D. 线性表的链式存储结构优于顺序存储结构
【解答】D
链式存储结构和顺序存储结构都有自己的优缺点。
(13)在单链表中,要将 s 所指节点插入到 p 所指节点之后,其语句应为( ) 。
A. s->next = p+1; p->next = s;
B. (*p).next = s; (*s).next = (*p).next;
C. s->next = p->next; p->next = s->next;
D. s->next = p->next; p->next = s;
【解答】D
(14)在双向链表存储结构中,删除 p 所指的节点时须修改指针( )。
A. p->next->prior = p->prior; p->prior->next = p->next;
B. p->next = p->next->next; p->next->prior = p;
C. p->prior->next = p; p->prior = p->prior->prior;
D. p->prior = p->next->next; p->next = p->prior->prior;
【解答】A
(15)在双向循环链表中,在 p 指针所指的节点后插入 q 所指向的新节点,其修改指针的
操作是( )。
A. p->next = q; q->prior = p; p->next->prior = q; q->next = q;
B. p->next = q; p->next->prior = q; q->prior = p; q->next = p->next;
C. q->prior = p; q->next = p->next; p->next->prior = q; p->next = q;
D. q->prior = p; q->next = p->next; p->next = q; p->next->prior = q;
【解答】C
2. 算法设计题
(1)将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中不允许有重复的数据。
【算法描述】
【完整代码】
【运行结果】
(2)将两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中允许有重复的数据。
【算法描述】
【完整代码】
【运算结果】
(3)已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计算法求出 A 与 B 的交集,并存放于A链表中。
【算法描述】
【完整代码】
【运行结果】
(4)已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计算法求出两个集合 A 和 B 的差集(即仅由在 A 中出现而不在 B 中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。
【算法描述】
【完整代码】
【运算结果】
(5)设计算法将一个带头结点的单链表A分解为两个具有相同结构的链表 B、C,其中 B 表的结点为 A 表中值小于零的结点,而 C 表的结点为 A 表中值大于零的结点(链表 A 中的元素为非零整数,要求 B、C 表利用 A 表的结点)。
【算法描述】
【完整代码】
【运算结果】
(6)设计一个算法,通过一趟遍历在单链表中确定值最大的结点。
【算法描述】
【完整代码】
【运行结果】
(7)设计一个算法,通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的存储空间。
【算法描述】
【完整代码】
【运算结果】
(8)设计一个算法,删除递增有序链表中值大于 mink 且小于 maxk 的所有元素(mink 和 maxk 是给定的两个参数,其值可以和表中的元素相同,也可以不同 )。
【算法描述】
【完整代码】
【运算结果】
(9)已知 p 指向双向循环链表中的一个结点,其结点结构为data、prior、next三个域,写出算法change(p),交换 p 所指向的结点和它的前缀结点的顺序。
【算法描述】
【完整代码】
【运算结果】
(10)已知长度为 n 的线性表A采用顺序存储结构,请写一时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法删除线性表中所有值为 item 的数据元素。
【算法描述】
【完整代码】
【运算结果】
第三章 栈和队列
1. 选择题
(1)若让元素 1, 2, 3, 4, 5 依次进栈,则出栈次序不可能出现在( )种情况。
A. 5, 4, 3, 2, 1
B. 2, 1, 5, 4, 3
C. 4, 3, 1, 2, 5
D. 2, 3, 5, 4, 1
【解答】C
栈是后进先出的线性表,然而C选项中 1 比 2 先出栈,违背了栈的后进先出原则,所以不可能出现C选项所示的情况。
A、1, 2, 3, 4, 5 依次全部进栈,再出栈,得到 5, 4, 3, 2, 1
B、1, 2 先进栈,然后出栈得到 2, 1,再 3, 4, 5 进栈,再出栈 5, 4, 3,合起来就是 2, 1, 5, 4, 3
D、1, 2 先进栈,然后 2 出栈,再 3, 4, 5 进栈,得到 2, 5, 4, 3,最后 1 出栈,就是 2, 5, 4, 3, 1
(2)若已知一个栈的入栈序列是 1,2,3… n,其输出序列为
, 若
,则
为( )。
A. i
B. n - i
C. n - i + 1
D. 不确定
【解答】C
(3)一个循环队列,f为当前队列头元素的前一位置,r为队尾元素的位置,假定队列中元素的个数小于n,计算队列中元素个数的公式为( )。
A. r - f
B. ( n + f - r ) % n
C. n + r - f
D. ( n + r - f ) % n
【解答】D
对于非循环队列,尾指针和头指针的差值便是队列的长度,而对于循环队列,差值可能为负数, 所以需要将差值加上MAXSIZE,然后与 MAXSIZE求余,即 ( r - f + n) % n 。
(4)链式栈结点为:(data, link),top 指向栈顶,若想删除栈顶节点,并将删除节点的值
保存到 x 中 ,则应执行操作( )。
A. x=top->data; top=top->link ;
B. top=top->link; x=top->link ;
C. x=top; top=top->link ;
D. x=top->link ;
【解答】A
先把将删除节点的值保存到 x 当中,即 x = top->data; 然后栈顶指针往后移,指向下一个节点,就是 top = top->link;
(5)设有一个递归算法如下
int fact(int n) { //n 大于等于 0 if(n <= 0) return 1; else return n * fact(n - 1); } 则计算 fact(n) 需要调用该函数的次数为( )。
A. n + 1
B. n - 1
C. n
D. n + 2
【解答】A
n = 0,===> fact(0)
n = 1,===> fact(1)-->fact(0)
n = 2,===> fact(2)-->fact(1)-->fact(0)
..........
(6)栈在( )中有所应用。
A. 递归调用 B. 函数调用 C. 表达式求值 D. 前三个选项都有
【解答】D
(7)为解决计算机主机与打印机间速度不匹配问题,通常设一个打印数据缓冲区。主机
将要输出的数据依次写入该缓冲区,而打印机则依次从该缓冲区中取出数据。该缓冲区的逻
辑结构应该是( )。
A. 队列 B. 栈 C. 线性表 D. 有序表
【解答】A
解决缓冲区问题应利用一种先进先出的线性表,所以选队列。
(8)设栈 S 和队列 Q 的初始状态为空,元素
和
依次进入栈 S,
一个元素出栈后即进入 Q,若 6 个元素出队的序列是
和
,则栈 S 的容
量至少应该是( )。
A. 2 B. 3 C. 4 D. 6
【解答】B
进栈,栈里有 (2个) ,然后出栈;
进栈,栈里有 (3个) ,然后出栈;
进栈,栈里有 (3个) ,然后出栈。
所以栈的容量至少是 3 。
(9)若一个栈以向量V[ 1…n ] 存储,初始栈顶指针top设为 n + 1,则元素x进栈的正确操作是( )。
A. top++; V[top] = x; B. V[top] = x; top++;
C. top–; V[top] = x; D. V[top] = x; top–;
【解答】C
栈顶指针top初始为 n + 1,那么这个数组是从后往前压的,应该先 top--,再压栈,不然第一个数就会溢出。
(10)设计一个判别表达式中左,右括号是否配对出现的算法,采用( )数据结构最佳。
A. 线性表的顺序存储结构 B. 队列
C. 线性表的链式存储结构 D. 栈
【解答】D
利用栈的后进先出原则。
(11)用链接方式存储的队列,在进行删除运算时( )。
A. 仅修改头指针 B. 仅修改尾指针
C. 头、尾指针都要修改 D. 头、尾指针可能都要修改
【解答】D
在有头节点的链队列的出队操作中,一般只需修改队头指针。但当队列中只有一个节点时,或者当队列中最后一个元素被删除时,该节点既是队头也是队尾,故删去此节点后队尾指针也会丢失,因此需对队尾指针重新赋值(指向头节点),使其指向头节点,且删去此节点后队列置空。
(12)循环队列存储在数组 A[0…m] 中,则入队时的操作为( )。
A. rear = rear + 1 B. rear = (rear + 1) % (m - 1)
C. rear = (rear + 1) % m D. rear = (rear + 1) % (m + 1)
【解答】D
数组 A[0…m] 中一共含有 m + 1 个元素,故在求模运算时应除以 m + 1。
(13)最大容量为 n 的循环队列, 队尾指针是 rear ,队头是 front ,则队空的条件是( )。
A. (rear+1)%n == front B. rear == front
C. rear+1 == front D. (rear-l)%n == front
【解答】B
最大容量为n的循环队列,队满条件是 (rear+1)%n==front,队空条件是rear==front 。
(14)栈和队列的共同点是( )。
A. 都是先进先出 B. 都是先进后出
C. 只允许在端点处插入和删除元素 D. 没有共同点
【解答】C
栈只允许在栈顶处进行插入和删除元素,队列只允许在队尾插入元素和在队头删除元素。
(15)一个递归算法必须包括( )。
A. 递归部分 B. 终止条件和递归部分
C. 迭代部分 D. 终止条件和迭代部分
【解答】B
2. 算法设计题
(1)将编号为 0 和 1 的两个栈存放于一个数组空间 V[m] 中,栈底分别处于数组的两端。当第 0 号栈的栈顶指针 top[0] 等于 -1 时该栈为空,当第 1 号栈的栈顶指针 top[1] 等于 m 时,该栈为空。两个栈均从两端向中间填充(见图3.17)。试编写双栈初始化,判断栈空、栈满、进栈和出栈等算法的函数。双栈数据结构的定义如下:
typedef struct { int top[2], bot[2]; //栈顶和栈底指针 SElemType *V; //栈数组 int m; //栈最大可容纳元素个数 }DblStack; 
【算法描述】
1、双栈初始化
初始化时,栈 0 的栈顶指针 top[0] 设置为 -1,栈 1 的栈顶指针 top[1] 设置为 m。栈 0 从数组的起始位置向中间增长,栈 1 从数组的末尾向中间增长。
2、判断栈空
由题目:当第 0 号栈的栈顶指针 top[0] 等于 -1 时该栈为空,当第 1 号栈的栈顶指针 top[1] 等于 m 时,该栈为空。
也就是说栈 0 为空的条件是 top[0] == -1,栈 1 为空的条件是 top[1] == m。
3、判断栈满
栈满的条件是两个栈的栈顶指针相邻,即 top[0] + 1 == top[1]。
4、进栈
5、出栈
(2)回文是指正读、反读均相同的字符序列,如 “abba” 和 “abba” 均是回文,但 “good” 不是回文。试设计算法判定给定的字符序列是否为回文。(提示:将一半字符入栈。)
【算法描述】
【完整代码】
【运算结果】
(3)设从键盘输入一整数的序列:
,试设计算法实现:用栈结构存储输入的整数,当
时,将
进栈;当
时,输出栈顶整数并出栈。算法应对异常情况(入栈满等)给出相应的信息。
【算法描述】
【完整代码】
【运算结果】
(4)从键盘上输入一个后缀表达式,试设计算法计算表达式的值。规定:逆波兰表达式的长度不超过一行,输入以 “$” 作为结束,操作数之间用空格分隔,操作符只可能有 “ + ” “ - ” “ * ” “ / ” 4种。 例如 : 234 34 + 2*$ 。
【算法描述】
【完整代码】
【运算结果】
(5)假设以 I 和 O 分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由 I 和 O 组成的序列, 称可以操作的序列为合法序列, 否则称为非法序列。
① 下面所示的序列中哪些是合法的?
A、IOIIOIOO B、IOOIOIIO C、IIIOIOIO D、IIIOOIOO
② 通过对①的分析, 写出一个算法, 判定所给的操作序列是否合法。 若合法, 返回 true ,否则返回 false (假定被判定的操作序列已存入一维数组中)。
① 选 A 和 D。
②【算法描述】
【完整代码】
【运算结果】
(6)假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素站点 ( 注意:不设头指针 ) ,试编写相应的置空队、判断队列是否为空、入队和出队等算法。
【算法描述】
1、置空队
2、判断队列是否为空
3、入队
4、出队
(7)假设以数组 Q[ m] 存放循环队列中的元素,同时设置一个标志 tag,以 tag== 0 和 tag == 1 来区别在队头指针(front)和队尾指针(rear)相等时,队列状态为 “空”还是 “满”。试编写与此结构相应的插入(enqueue)和删除(dlqueue)算法。
【算法描述】
【完整代码】
【运算结果】
(8)如果允许在循环队列的两端进行插入和删除操作。要求:
① 写出循环队列的类型定义;
② 写出“从队尾删除”和“从队头插入”的算法。
① 循环队列的类型定义
【算法描述】
② 1、从队尾删除的算法
【算法描述】
2、从队头插入的算法
【算法描述】
【完整代码】
【运算结果】
(9)已知 Ackermann 函数定义如下 :
① 写出计算 Ack(m, n) 的递归算法,并根据此算法给出出 Ack(2, 1) 的计算过程;
② 写出计算 Ack(m, n) 的非递归算法。
① Ack(m, n) 的递归算法
【算法描述】
【完整代码】
【运算结果】
② Ack(m, n) 的非递归算法
【算法描述】
【完整代码】
【运算结果】
(10)已知 f 为单链表的表头指针 , 链表中存储的都是整型数据,试写出实现下列运算的递归算法:
① 求链表中的最大整数;
② 求链表的结点个数;
③ 求所有整数的平均值。
【算法描述】
① 求链表中的最大整数
② 求链表的结点个数
③ 求所有整数的平均值
【完整代码】
【运算结果】
第四章 串、数组和广义表
1. 选择题
(1)串是一种特殊的线性表,其特殊性体现在( )。
A. 可以顺序存储 B. 数据元素是一个字符
C. 可以链式存储 D. 数据元素可以是多个字符若
【解答】B
(2)串下面关于串的的叙述中,( )是不正确的。
A. 串是字符的有限序列 B. 空串是由空格构成的串
C. 模式匹配是串的一种重要运算 D. 串既可以采用顺序存储,也可以采用链式存储
【解答】B
空格常常是串的字符集合中的一个元素,由一个或多个空格组成的串成为空格
串,零个字符的串成为空串,其长度为零。
(3)串“ ababaaababaa ”的 next 数组为( )。
A. 012345678999 B. 012121111212 C. 011234223456 D. 0123012322345
【解答】C
首先 j = 1 的时候,next[1] = 0;
j = 2,1<k<2,next[2] = 1;
j = 3,1<k<3,k = 2,然后比较与是否相等,该题中,则 next[3] = 1;
j = 4,1<k<4,k = 2、3;当 k = 2 时,比较与, ;
当 k = 3 时,比较与,即;
综上,所以 next[4] = 2;
......
(4)串“ ababaabab ”的 nextval 为( )。
A. 010104101 B. 010102101 C. 010100011 D. 010101011
【解答】A
该题前六位元素"ababaa"用上题的next[j] : 011234
首先默认 j = 1 时,nextval[1] = 0;
j = 2 时,该元素(b)对应的 next 值为 1,则用该元素(b) 与 j = 1 对应的元素(a)比较,不相等,则 它对应的 nextval 值 就等于 其 next 值,即 nextval[2] = next[2] = 1;
j = 3 时,该元素(a)对应的 next 值为 1,则用该元素(a) 与 j = 1 对应的元素(a)比较,相等,则 它对应的 nextval 值 就等于 j = 1的 nextval 值,即 nextval[3] = nextval[0] = 0;
......
j = 6 时,该元素(a)对应的 next 值为 4,则用该元素(a) 与 j = 4 对应的元素(b)比较,不相等,则 它对应的 nextval 值 就等于其 next 值,即 nextval[6] = next[6] = 4;
......
(5)串的长度是指( )。
A. 串中所含不同字母的个数 B. 串中所含字符的个数
C. 串中所含不同字符的个数 D. 串中所含非空格字符的个数
【解答】B
串中字符的数目n称为串的长度。
(6)假设以行序为主序存储二维数组 A = array[1…100, 1…100] ,设每个数据元素占 2 个存
储单元,基地址为 10,则 LOC[5, 5] =( )。
A. 808 B. 818 C. 1010 D. 1020
【解答】B
以行序为主,则 LOC[5,5]=[(5-1)*100+(5-1)]*2+10=818 。
(7)设有数组 A[i,j] ,数组的每个元素长度为 3 字节, i 的值为 1 到 8,j 的值为 1 到 10,数组从内存首地址 BA 开始顺序存放, 当用以列为主存放时, 元素 A[5, 8] 的存储首地址为( )。
A. BA + 141
B. BA + 180
C. BA + 222
D. BA + 225
【解答】B
以列序为主,则 LOC[5, 8]=[(8-1)*8+(5-1)]*3+BA=BA+180 。
(8)设有一个 10 阶的对称矩阵 A ,采用压缩存储方式,以行序为主存储,
为第一元
素,其存储地址为 1,每个元素占一个地址空间,则
的地址为( )。
A. 13
B. 32
C. 33
D. 40
【解答】C
中 i = 8, j = 5, i > j,所以根据公式 i(i - 1)/2 + (j - 1) + 1,得出答案选C。
(9)若对 n 阶对称矩阵 A 以行序为主序方式将其下三角形的元素 (包括主对角线上所有元素 ) 依次存放于一维数组 B[1…(n(n + 1)) / 2] 中,则在 B 中确定
( i < j )的位置 k 的关系为( )。
A. i * (i - 1) / 2 + j
B. j * (j - 1) / 2 + i
C. i * (i +1) / 2 + j
D. j * (j +1) / 2 + i
【解答】B
(10)二维数组 A 的每个元素是由 10 个字符组成的串,其行下标 i=0, 1, , , 8,列下标 j = 1, 2, ......, 10 。若 A 按行先存储,元素 A[8, 5] 的起始地址与当 A 按列先存储时的元素( )的起始地址相同。设每个字符占一个字节。
A. A[8, 5]
B. A[3, 10]
C. A[5, 8]
D. A[0, 9]
【解答】B
设数组从内存首地址 LOC(0, 1) 开始顺序存放,若数组按行先存储,元素 A[8,5] 的起始地址为: LOC(0, 1)+[( 8-0 )*10+ (5-1)]*1=LOC(0, 1)+84 ;若数组按列先存储,易计算出元素 A[3,10] 的起始地址为: M+[ (10-1) *9+ ( 3-0 ) ]*1=M+84 。故选 B。
(11)设二维数组 A[1… m, 1… n] (即 m 行 n 列)按行存储在数组 B[1… m*n] 中,则二维
数组元素 A[i, j] 在一维数组 B 中的下标为( )。
A. ( i - 1)n + j B. ( i - 1)n + j -1 C. i ( j - 1) D. jm + i - 1
【解答】A
由题意可知 A[1, 1] = 1。
所以 A[i, j] 在一维数组 B 中的下标为 (i - 1)*n + (j - 1) + 1(首地址),即选A。
(12)数组 A[0…4, -1…-3, 5…7] 中含有元素的个数( )。
A. 55 B. 45 C. 36 D. 16
【解答】B
我们知道一个二维数组 Array[m][n]的元素个数为 。
该数组是一个三维数组,可以理解为一个长方体,0 ~ 4 共有 5 行,-1 ~ -3 共有 3 列,5 ~ 7 共有 3 纵,所以一共有 5 * 3 * 3 = 45 个元素。
(13)广义表 A = (a, b, (c, d), (e, (f, g))) ,则 Head(Tail(Head(Tail(Tail(A))))) 的值为( )。
A. (g) B. (d) C. c D. d
【解答】D
首先 Tail(A) = (b, (c, d), (e, (f, g)));
然后 Tail(Tail(A)) = ((c, d), (e, (f, g)));
然后 Head(Tail(Tail(A))) = (c, d);
Tail(Head(Tail(Tail(A)))) = (d);
Head(Tail(Head(Tail(Tail(A))))) = d
(14)广义表 ((a, b, c, d)) 的表头是() ,表尾是( )。
A. a B. ( ) C. (a,b,c,d) D. (b,c,d)
【解答】C、 B
(15)设广义表 L=((a, b, c)) ,则 L 的长度和深度分别为( )。
A. 1 和 1 B. 1 和 3 C. 1 和 2 D. 2 和 3
【解答】C
广义表的长度是指广义表中所含元素的个数,广义表的深度是指广义表中展开后所含括号的层数。所以该题中 L 的长度为 1,深度为 2。
2.应用题
(1)已知模式串 t = “ abcaabbabcab ” 写出用 KMP法求得的每个字符对应的 next 和 nextval
函数值。
【解答】
(2)设目标为 t = “ abcaabbabcabaacbacba ”,模式为 p = “ abcabaa ”。
① 计算模式 p 的 naxtval 函数值;
② 画出利用 KMP算法进行模式匹配时每一趟的匹配过程。
【解答】
① 计算模式 p 的 naxtval 函数值;
② 画出利用 KMP算法进行模式匹配时每一趟的匹配过程。
(3)数组 A 中,每个元素 A[i, j] 的长度均为 32 个二进制位,行下标从 -1 ~ 9,列下标从 1 到 11,从首地址 S 开始连续存放主存储器中,主存储器字长为 16 位。求:
① 存放该数组所需多少单元?
② 存放数组第 4 列所有元素至少需多少单元?
③ 数组按行存放时,元素 A[7, 4] 的起始地址是多少?
④ 数组按列存放时,元素 A[4, 7] 的起始地址是多少?
【解答】
① 存放该数组所需多少单元?
主存储器字长 16 位,即 2 个字节,-1 ~ 9 一共 11 行,1~11一个 11 列,故该数组存放需要单位数为:11*11*2 = 242。
② 存放数组第 4 列所有元素至少需多少单元?
11*2 = 22 个单元。
③ 数组按行存放时,元素 A[7, 4] 的起始地址是多少?
(8 * 11 + 3) * 2 + s = s + 182
④ 数组按列存放时,元素 A[4, 7] 的起始地址是多少?
(6 * 11 + 5) * 2 + s = s + 142
(4)请将香蕉(banana)用工具 H( ) — Head( ) , T( ) — Tail( ) 从 L 中取出。
L = (apple, (orange, (strawberry, (banana)), peach), pear)
【解答】
故答案是 H ( H ( T ( H ( T ( H ( T(L) ) ) ) ) )
3. 算法设计题
(1)设计一个算法统计在输入字符串中各个不同字符出现的频度并将结果存入文件 (字符串中的合法字符为 A - Z 这 26 个字母和 0 - 9 这 10 个数字)。
【算法描述】
【完整代码】
【运算结果】
(2)设计一个递归算法来实现字符串逆序存储,要求不另设串存储空间。
【算法描述】
【完整代码】
【运算结果】
(3)设计算法,实现下面函数的功能。函数 void insert(char*s, char*t, int pos) 将字符串 t 插入到字符串 s 中,插入位置为 pos 。假设分配给字符串 s 的空间足够让字符串 t 插入。(说明:不得使用任何库函数)
【算法描述】
【完整代码】
【运算结果】
(4)已知字符串 s1 中存放一段英文,写出算法 format(s1,s2,s3,n),将其按给定的长度 n 格式化成两端对齐的字符串 s1(长度为 n 且首尾),其多余的字符送 s3。
【算法描述】
【完整代码】
【运算结果】
(5)设二维数组 a[1…m, 1…n] 含有 m*n 个整数。
① 写一个算法判断 a 中所有元素是否互不相同 ?输出相关信息 (yes / no) ;
② 试分析算法的时间复杂度。
① 判断 a 中所有元素是否互不相同 ?输出相关信息 (yes / no)
【算法描述】
【完整代码】
【运算结果】
② 试分析算法的时间复杂度
该算法的时间复杂度为
因为最外层的for循环 for(int i = 0; i < m; i++) 执行 m 次,
第二层for循环 for(int j = 0; j < n; j++) 执行 n 次,后面两层也是依次执行 m、n次。
(6)设任意 n 个整数存放于数组 A(1: n) 中,试编写算法,将所有正数排在所有负数前面(要求算法复杂度为 0(n) )。
【算法描述】
【完整代码】
【运算结果】
第五章 树和二叉树
1. 选择题
(1)把一棵树转换为二叉树后,这棵二叉树的形态是( ) 。
A. 唯一的
B. 有多种
C. 有多种,但根节点都没有左孩子
D. 有多种,但根节点都没有右孩子
【解答】A
因为二叉树有左孩子、右孩子之分,故一棵树转换为二叉树后,这棵二叉树的
形态是唯一的。
(2)由 3 个结点可以构造出多少种不同的二叉树?( )
A. 2 B. 3 C. 4 D. 5
【解答】D
二叉树有左右之分。
(3)一棵完全二叉树上有 1001 个节点,其中叶子节点的个数是( )。
A. 250 B. 500 C. 254 D. 501
【解答】D
设是度为 0 节点(叶子节点)个数,是度为 1 的节点个数,是度为 2 的节点个数,因此可得,且,化简得到,由完全二叉树的性质可得= 0 或 1,又因为为整数,所以= 0, = 500,= 501,即有 501 个叶子节点。
(4)一个具有 1025 个节点的二叉树的高 h 为( )。
A. 11 B. 10 C. 11 ~ 1025 D. 10 ~ 1024
【解答】C
若每层仅有一个节点,则树高 h 为 1025 ;
根据二叉树的性质 4 :具有 n 个节点的完全二叉树的深度为 ,可知该二叉树最小数高为, 即选C。
(5)深度为 h 的满 m叉树的第 k 层有()个节点。
A.
B.
C.
D.
【解答】A
深度为 h 的满 m 叉树共有个节点,第 k 层有个节点。
(6)利用二叉链表存储树,则根节点的右指针是( )。
A. 指向最左孩子 B. 指向最右孩子 C. 空 D. 非空
【解答】C
利用二叉链表表示法存储树时,右指针指向兄弟节点,因为根节点没有兄弟节点,故根节点的右指针指向空。
(7)对二叉树的节点从 1 开始进行连续编号,要求每个节点的编号大于其左、右孩子的编号,同一节点的左右孩子中,其左孩子的编号小于其右孩子的编号,可采用( )遍历实现编号。
A. 先序 B. 中序 C. 后序 D. 从根开始按层次遍历
【解答】C
若是从大到小,则是中、右、左的顺序,
若是从小到大,则是左、右、中的顺序,即后序遍历。
(8)在一棵度为 4 的树 T 中,若有 20 个度为 4 的节点,10 个度为 3 的节点,1 个度为 2 的节点,10 个度为 1 的节点,则树 T 的叶节点个数是( )。
A. 41 B. 82 C. 113 D. 122
【解答】B
设树 T 的总叶子个数为 n,叶子节点的个数为,度为 2 的节点的个数为,度为 3 的节点的个数为,度为 4 的节点的个数为,
所以,
又因为 n = B(分支总数) + 1,
可算出,
所以 n = 122 + 1 = 123 = 41 +,由此可算出叶子节点个数为82。
(9)在下列存储结构表示法中,( )不是树的存储结构表示法。
A. 双亲表示法 B. 孩子链表表示法 C. 孩子兄弟表示法 D. 顺序存储表示法
【解答】D
树的存储结构有三种:双亲表示法、孩子表示法、孩子兄弟表示法,其中孩子兄弟表示法是常用的表示法,任意一棵树都能通过孩子兄弟表示法转换为二叉树进行存储。
(10)一棵非空的二叉树的先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足( )。
A. 所有的节点均无左孩子
B. 所有的节点均无右孩子
C. 只有一个叶子节点
D. 是任意一棵二叉树
【解答】C
因为先序遍历结果是“中左右” ,后序遍历结果是“左右中” ,当没有左子树时,就是“中右”和“右中” ;当没有右子树时,就是“中左”和“左中” 。则所有的节点均无左孩子或所有的节点均无右孩子均可,但题目问的是一定满足的条件,所以 A、B 不能选,又所有的节点均无左孩子与所有的结点均无右孩子时,均只有一个叶子节点,故选 C。
(11)设哈夫曼树中有 199 个节点,则该哈夫曼树中有( )个叶子节点。
A. 99 B. 100 C. 101 D. 102
【解答】B
在哈夫曼树中没有度为 1 的节点,只有度为 0(叶子节点)和度为 2 的节点。设叶子节点的个数为,度为 2 的节点的个数为,由二叉树的性质,则总节点数 ,得到。
(12)若 X 是二叉中序线索树中一个有左孩子的节点,且 X 不为根,则 X 的前驱为( )。
A. X 的双亲
B. X 的右子树中最左的节点
C. X 的左子树中最右节点
D. X 的左子树中最右叶节点
【解答】C
例如下图中的二叉树,X的前驱为 F 。
(13)引入二叉线索树的目的是( )。
A. 加快查找节点的前驱或后继的速度
B. 为了能在二叉树中方便的进行插入与删除
C. 为了能方便的找到双亲
D. 使二叉树的遍历结果唯一
【解答】A
(14)设 F 是一个森林, B 是由 F 变换得的二叉树。若 F 中有 n 个非终端节点,则 B 中右指针域为空的节点有( )个。
A. n - 1 B. n C. n + 1 D. n + 2
【解答】C
森林转换成二叉树,即用到孩子兄弟表示法。
非终端节点有 n 个,设森林总节点个数为 m,则终端节点(即叶子节点)个数为 m - n,一个节点有两个指针域,左孩子右兄弟,所以总指针域个数为 2m 个。
根据二叉树的特性,可知在 m 个节点的二叉链表中,有 m + 1 个空指针域。
【除根节点外,每出现一个节点就会占用其父节点的一个指针域,所以占据 m - 1个指针域,即使用的指针域为 m - 1,所以空指针域为 2m - (m - 1) = m + 1】(这里不需要考虑孩子兄弟表示法,就是普通的一个二叉树)
终端节点转化为二叉树后,该节点没有左孩子,左指针域就为空,即 m - n。
因为森林转二叉树后,左孩子是第一个孩子,右孩子是兄弟,所以终端节点转化后一定无左孩子,右孩子可能有也可能没有,也就是说转化后有两种可能,一是仍为叶子节点,二为不再是叶子节点,但只有右孩子。
右指针域为空个数 = 总的空指针域个数 - 左指针域为空的个数
所以右指针域为空的个数为:(m + 1) - (m - n) = n + 1。
(15)
个权值均不相同的字符构成哈夫曼树, 关于该树的叙述中, 错误的是( )。
A. 该树一定是一棵完全二叉树
B. 树中一定没有度为 1 的节点
C. 树中两个权值最小的节点一定是兄弟节点
D. 树中任一非叶节点的权值一定不小于下一层任一节点的权值
【解答】A
哈夫曼树的构造过程是每次都选取权值最小的树作为左右子树构造一棵新的二叉树,所以树中一定没有度为 1 的节点、两个权值最小的结点一定是兄弟节点、任一非叶节点的权值一定不小于下一层任一节点的权值。
2. 应用题
(1)试找出满足下列条件的二叉树
① 先序序列与后序序列相同。
② 中序序列与后序序列相同。
③ 先序序列与中序序列相同。
④ 中序序列与层次遍历序列相同。
【解答】
先序遍历:中—左—右;
中序遍历:左—中—右;
后序遍历:左—右―中。
层次遍历就是一层一层从左往右依次遍历,相当于“中—左—右”,即先序遍历。
① 先序和后序相同,那么左右子树一样,没有根节点,故该二叉树或为空树,或为只有根结点的二叉树;
② 中序和后序相同,那么左中子树一样,故该二叉树或为空树,或为任一结点至多只有左子树的二叉树;
③ 先序和中序相同,那么中右子树一样,故该二叉树或为空树,或为任一结点至多只有右子树的二叉树;
④ 与③一样。
(2)设一棵二叉树的先序序列: A B D F C E G H ,中序序列: B F D A G E H C
① 画出这棵二叉树。
② 画出这棵二叉树的后序线索树。
③ 将这棵二叉树转换成对应的树(或森林) 。
【解答】
①
② 该二叉树的后序遍历(左-右-中)为:F D B G H E C A 。
则后序线索树如下:
③ 将这棵二叉树转换成对应的树(或森林)。
将随便一棵树转化为二叉树采用了左孩子右兄弟法。反过来。
(3)假设用于通信的电文仅由 8 个字母组成,字母在电文中出现的频率分别为 0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.10。
① 试为这 8 个字母设计哈夫曼编码。
② 试设计另一种由二进制表示的等长编码方案。
③ 对于上述实例,比较两种方案的优缺点。
【解答】
① 试为这 8 个字母设计哈夫曼编码。
② 试设计另一种由二进制表示的等长编码方案。
因为有八位数,所以二进制编码是三位,即设从左到右 0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.10 的二进制等长编码依次依次是000、001、010、011、100、101、110、111。
③ 对于上述实例,比较两种方案的优缺点。
对于第 ① 种,
其WPL = (0.02+0.03)*5+(0.06+0.07+0.10)*4+(0.32+0.21+0.19)*2 = 2.61
对于第 ② 种,
其WPL = (0.07+0.19+0.02+0.06+0.32+0.03+0.21+0.10)*3 =
综上比较哈夫曼编码优于等长二进制编码。
(4)已知下列字符 A、B、C、D、E、F、G 的权值分别为 3、12 、7、4、2、8,11,试填写出其对应哈夫曼树 HT 的存储结构的初态和终态。
【解答】
对应的哈夫曼树如下:
HT 的初态:
HT 的终态:
3. 算法设计题
以二叉链表作为二叉树的存储结构,设计以下算法。
(1)统计二叉树的叶节点个数。
【算法描述】
【完整代码】
【运算结果】
(2)判别两棵树是否相等。
【算法描述】
【完整代码】
【运算结果】
(3)交换二叉树每个节点的左孩子和右孩子。
【算法描述】
【完整代码】
【运算结果】
(4)设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个节点来说,先访问
这个节点,再按双序遍历它的左子树,然后再一次访问这个节点,接下来按双序遍历它的右
子树)。
【算法描述】
【完整代码】
【运算结果】
(5)计算二叉树最大的宽度 (二叉树的最大宽度是指二叉树所有层中节点个数的最大值) 。
【算法描述】
【完整代码】
【运算结果】
(6)用按层次顺序遍历二叉树的方法,统计树中度为 1 的节点数目。
【算法描述】
“度为 1 的节点”指的是只有一个子节点的节点。
【完整代码】
【运算结果】
(7)求任意二叉树中第一条最长的路径长度,并输出此路径上各节点的值。
【算法描述】
【完整代码】
【运算结果】
(8)输出二叉树中从每个叶子节点到根节点的路径。
【算法描述】
【完整代码】
【运算结果】
第六章 图
1. 选择题
(1)在一个无向图中,所有顶点的度数之和等于图的边数的( )倍。
A. 1/2 B. 1 C. 2 D. 4
【解答】C
每条边连接两个顶点,因此每条边对应顶点的度数为2,因此所有顶点的度数之和等于所有边数的2倍。
(2)在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的( )倍。
A. 1/2 B. 1 C. 2 D. 4
【解答】B
有向图中所有顶点入度之和等于所有顶点出度之和。
(3)具有 n 个顶点的有向图最多有( )条边。
A. n B. n(n-1) C. n(n+1) D.
【解答】B
每个顶点都可以有 (n - 1) 条边,又因为有向图有方向之分,然后 n 个顶点,就最多有 n(n - 1)条边。
若是具有 n 个顶点的无向图,则最多有 n(n - 1)/2 条边。因为无向图没有方向。
(4)n 个顶点的连通图用邻接距阵表示时,该距阵至少有( )个非零元素。
A. n B. 2(n-1) C. n/2 D.
【解答】B
所谓连通图一定是无向图,有向的叫做强连通图。
连通图:任意一个顶点到另一个顶点直接都有路径。(注!!路径并非指一条边)
完全图:任意两个点都有一条边相连。
连通图 完全图
连通图有 n 个顶点,则至少只需要 n - 1 条边。由于无向图的每条边同时关联了两个顶点,因此邻接矩阵中每条边被存储了两次(也就是对称矩阵),因此至少有 2(n - 1) 个非零元素。
(5)G 是一个非连通无向图,共有 28 条边,则该图至少有( )个顶点。
A. 7 B. 8 C. 9 D. 10
【解答】C
与第(3)题类似。
若是具有 n 个顶点的无向图,则最多有 n(n - 1)/2 条边。
8 个顶点的无向图最多有 8(8 - 1)/2 = 28 条边,此时的话就是连通图,所以需要再添加一个点即构成非连通无向图,故至少有 9 个顶点。第九个节点是孤立的,不与任何节点通。
(6)若从无向图的任意一个顶点出发进行一次深度优先搜索可以访问图中所有的顶点,则该图一定是( )图。
A. 非连通 B. 连通 C. 强连通 D. 有向
【解答】B
首先题目中是无向图,所以排除 C、D 两个选项。
从该无向图任意一个顶点出发有到各个顶点的路径, 所以该无向图是连通图。
(7)下面( )算法适合构造一个稠密图 G 的最小生成树。
A. 普里姆算法(Prim) B. 克鲁斯卡尔算法(Kruskal)
C. 弗洛伊德算法(Floyd) D. 迪杰斯特拉算法(Dijkstra)
【解答】A
普里姆算法适合构造一个稠密图 G 的最小生成树。(归并顶点)
克鲁斯卡尔算法适合构造一个稀疏图 G 的最小生成树。(归并边)
弗洛伊德算法是求每一对顶点之间的最短路径。
迪杰斯特拉算法是就从某个源点到其余各顶点的最短路径。
(8)用邻接表表示图进行广度优先遍历时,通常借助( )来实现算法。
A. 栈 B. 队列 C. 树 D. 图
【解答】B
广度优先遍历通常借助队列来实现算法,深度优先遍历通常借助栈来实现算法。
深度优先遍历使用递归实现,故用到了栈。
广度优先遍历,每次需要确保当前层的所有结点被访问到,要用队列存储。
(9)用邻接表表示图进行深度优先遍历时,通常借助( )来实现算法。
A. 栈 B. 队列 C. 树 D. 图
【解答】A
(10)深度优先遍历类似于二叉树的( )。
A. 先序遍历 B. 中序遍历 C. 后序遍历 D. 层次遍历
【解答】A
(11)广度优先遍历类似于二叉树的( )。
A. 先序遍历 B. 中序遍历 C. 后序遍历 D. 层次遍历
【解答】D
(12)图的 BFS 生成树的树高比 DFS 生成树的树高( )。
A. 小 B. 相等 C. 小或相等 D. 大或相等
【解答】C
BFS:广度优先遍历 DFS:深度优先遍历
对于一些特殊的图,比如只有一个顶点的图,其 BFS 生成树的树高和 DFS 生成树的树高相等。一般的图,根据图的 BFS 生成树和 DFS 树的算法思想, BFS 生成树的树高比 DFS 生成树的树高小。
(13)已知图的邻接矩阵如图 6.30 所示, 则从顶点
出发按深度优先遍历的结果是( )。

【解答】C
按深度优先遍历:
从 开始,看第一行,假设它先遇到的是 (也可以是、、、);
然后再看 这一行,这里到这个就不需要再看了,因为的时候已经算过了,再假设先遇到的顶点是 (也可以是);
再看 这一行,先遇到 ,再看 这一行,先遇到 ,再看 这一行,发现 0 和 4 都遍历过了,退回到 , 也遍历过了,遇到 ,看 这一行,遇到 ,结束。
综上就是 0 1 3 4 2 5 6 ,所以选 C。
邻接矩阵唯一 =====> 深度遍历结果不唯一
再以选项 A 为例:
首先 到 ,然后看 这一行,到 ,再到 ,再到 ,然后看 这一行,发现 到 是没有路径的,所以 A 选项错误。
(14)已知图的邻接表如图 6.31 所示,则从顶点
出发按广度优先遍历的结果是( ),按深度优先遍历的结果是( )。

A. 0 1 3 2 B. 0 2 3 1 C. 0 3 2 1 D. 0 1 2 3
【解答】D、D
由该链表可知,此图为无向图。
广度优先遍历,则先从 出发,直接读取邻接表第一行,即 0 1 2 3。
深度优先遍历,从 出发,到 ,再看 那一行,到 ,最后再到 ,即 0 1 2 3。
如果根据该链表将此无向图画出来,再根据图按广度优先遍历的话,C 选项也可以,但是该题已经给出了链表,所以已经确定了遍历的顺序,故只能先遍历 。
(15)下面( )方法可以判断出一个有向图是否有环。
A. 深度优先遍历 B. 拓扑排序 C. 求最短路径 D. 求关键路径
【解答】B
2. 应用题
(1)已知图 6.32 所示的有向图,请给出:

① 每个顶点的入度和出度;
② 邻接矩阵;
③ 邻接表;
④ 逆邻接表。
【解答】
① 每个顶点的入度和出度
顶点 1 的入度为 3,出度为 0; 顶点 2 的入度为 2,出度为 2;
顶点 3 的入度为 1,出度为 2; 顶点 4 的入度为 1,出度为 3;
顶点 5 的入度为 2,出度为 1; 顶点 6 的入度为 2,出度为 3;
② 邻接矩阵
③ 邻接表
④ 逆邻接表
(2)已知如图 6.33 所示的无向网,请给出:

① 邻接矩阵;
② 邻接表;
③ 最小生成树
【解答】
① 邻接矩阵
② 邻接表
③ 最小生成树
根据普里姆算法或者克鲁斯卡尔算法可以得到对应的最小生成树。
(3)已知图的邻接矩阵如图 6.34 所示。试分别画出自顶点 1 出发进行遍历所得的深度优先生成树和广度优先生成树 。

【解答】
(4)有向网如图 6.35 所示,试用迪杰斯特拉算法求出从顶点 a 到其他各顶点间的最短路径,完成表 6.9。


【解答】
由上图可知顶点 a 到各个顶点的最短路径为:b----15、c----2、d----11、e----10、f----6、g----14。
(5)试对图 6.36 所示的 AOE- 网:

① 求这个工程最早可能在什么时间结束;
② 求每个活动的最早开始时间和最迟开始时间;
③ 确定哪些活动是关键活动。
【解答】
① 求这个工程最早可能在什么时间结束
由第一张表可以看出,该工程最早完成结束的时间为 43。
② 求每个活动的最早开始时间和最迟开始时间
见第二张表,e(i) 表示活动的最早开始时间,l(i) 表示活动最晚开始时间。
③ 确定哪些活动是关键活动
对于关键活动,e(i) = l(i),即 l(i) - e(i) = 0,根据第二张表,可看出关键活动有:
<1, 3>、<3, 2>、<2, 5>、<5, 6>。
3. 算法设计题
(1)分别以邻接矩阵和邻接表作为存储结构,实现以下图的基本操作:
① 增加一个新顶点 v,函数为 InsertVex(G,v);
② 删除顶点 v 及其相关的边,函数为 DeleteVex(G,v);
③ 增加一条边 <v, w>,函数为 InsertArc(G,v,w);
④ 删除一条边 <v, w>,函数为 DeleteArc(G , v, w)。
1、以邻接矩阵作为存储结构
【算法描述】
2、以邻接表作为存储结构
【算法描述】
(2)一个连通图采用邻接表作为存储结构,设计一个算法,实现从顶点 v 出发的深度优先遍历的非递归过程。
【算法描述】
【完整代码】
【运算结果】
(3)设计一个算法,求图 G 中距离顶点 v 的最短路径长度最大的一个顶点,设 v 可达其余各个顶点。
【算法描述】
【完整代码】
【运算结果】
(4)试基于图的深度优先搜索策略设计一算法, 判别以邻接表方式存储的有向图中是否存在由顶点
到顶点
的路径( i ≠ j )。
【算法描述】
【完整代码】
【运算结果】
(5)采用邻接表存储结构,设计一个算法,判别无向图中任意给定的两个顶点之间是否存在一条长度为为 k 的简单路径。
【算法描述】
【完整代码】
【运算结果】
第七章 查找
1. 选择题
(1)对 n 个元素的表做顺序查找时, 若查找每个元素的概率相同, 则平均查找长度为( )。
A. (n-1) / 2
B. n / 2
C. (n+1) / 2
D. n
【解答】C
总查找次数N = 1 + 2 + 3 + ...... + n = n(n+1) / 2 ,则平均查找长度为 N / n = (n+1) / 2。
因为每个元素查找的概率相同,所以,
故
(2)适用于折半查找的表的存储方式及元素排列要求为( )。
A. 链接方式存储,元素无序
B. 链接方式存储,元素有序
C. 顺序方式存储,元素无序
D. 顺序方式存储,元素有序
【解答】D
折半查找要求线性表必须采用顺序存储结构, 而且表中元素按关键字有序排列。
(3)如果要求一个线性表既能较快的查找,又能适应动态变化的要求,最好采用( )查找法。
A. 顺序查找 B. 折半查找 C.分块查找 D. 哈希查找
【解答】C
分块查找的优点是: 在表中插入和删除数据元素时, 只要找到该元素对应的块,就可以在该块内进行插入和删除运算。由于块内是无序的,故插入和删除比较容易,无需进行大量移动。如果线性表既要快速查找又经常动态变化,则可采用分块查找。
(4)折半查找有序表( 4, 6, 10, 12, 20 , 30 , 50 , 70 , 88 , 100 )。若查找表中元素58,则它将依次与表中( )比较大小,查找结果是失败。
A. 20 , 70, 30, 50
B. 30, 88, 70 , 50
C. 20 , 50
D. 30 , 88, 50
【解答】A
表中共 10 个元素, 第一次取 mid=(1+10)/2=5,与第五个元素 20 比较, 58 大于 20,low=mid+1,即看[6,10],再取 (6+10)/2=8,与第八个元素 70 比较,依次类推再与 30 、 50 比较,最终查找失败。
(5)对 22 个记录的有序表作折半查找,当查找失败时,至少需要比较( )次关键字。
A. 3 B. 4 C. 5 D. 6
【解答】B
22 个记录的有序表,其折半查找的判定树深度为,且该判定树不是满二叉树,即查找失败时至多比较 5 次,至少比较 4 次。
至少需要4次,
第一次:与第11个位置上的数进行比较 mid=(1+22)/2=11,查找失败进入[1,10]区域进行查找
第二次:与第5个位置上的数进行比较 mid=(1+10)/2=5,查找失败进入[1,4]区域进行查找
第三次:与第2个位置上的数进行比较 mid=(1+4)/2=2,查找失败进入[1,2]区域进行查找
第四次:与第1个位置上的数进行比较 查找失败说明不存在该关键字
(6)折半搜索与二叉排序树的时间性能( )。
A. 相同 B. 完全不同 C. 有时不相同 D. 数量级都是
【解答】C
(7)分别以下列序列构造二叉排序树,与用其它三个序列所构造的结果不同的是( )。
A.( 100 , 80, 90 , 60, 120 , 110 , 130)
B.( 100 , 120 , 110 , 130 , 80, 60 , 90)
C.( 100 , 60, 80 , 90, 120 , 110 , 130)
D.(100 , 80 , 60, 90 , 120 , 130 , 110)
【解答】C
A 、 B、 C、 D 四个选项构造二叉排序树都以 100 为根,易知 A 、 B、 D 三个序列中第一个比 100 小的关键字为 80,即 100 的左孩子为 80 ,而 C 选项中 100 的左孩子为 60,故选 C。
A、B、D所构造的二叉排序树如下:
而 C 选项对应的二叉排序树如下:
(8)在平衡二叉树中插入一个节点后造成了不平衡,设最低的不平衡节点为 A ,并已知A 的左孩子的平衡因子为 0 右孩子的平衡因子为 1,则应作( )型调整以使其平衡。
A. LL B. LR C. RL D. RR
【解答】C
该题最简单的插入后的树如下:
由图可知,是在右孩子的左孩子进行插入,故应进行 RL 旋转调整。
(9)下列关于 m 阶 B- 树的说法错误的是( )。
A. 根节点至多有 m 棵子树
B. 所有叶子都在同一层次上
C. 非叶节点至少有 m/2 (m 为偶数 )或 m/2+1 ( m 为奇数)棵子树
D. 根节点中的数据是有序的
【解答】C
根节点关键字数量最少为 1,最多为 m - 1。
其他非叶节点关键字数量最少为 m / 2 (向上取整),最多为 m - 1。
根节点可以为终端节点,那么没有子树。
(10)下面关于 B- 和 B+ 树的叙述中,不正确的是( )。
A. B- 树和 B+ 树都是平衡的多叉树
B. B- 树和 B+ 树都可用于文件的索引结构
C. B- 树和 B+ 树都能有效地支持顺序检索
D. B- 树和 B+ 树都能有效地支持随机检索
【解答】C
(11)m 阶 B- 树是一棵( )。
A. m 叉排序树
B. m 叉平衡排序树
C. m-1 叉平衡排序树
D. m+1 叉平衡排序树
【解答】B
(12)下面关于哈希查找的说法,正确的是( )。
A. 哈希函数构造的越复杂越好,因为这样随机性好,冲突小
B. 除留余数法是所有哈希函数中最好的
C. 不存在特别好与坏的哈希函数,要视情况而定
D. 哈希表的平均查找长度有时也和记录总数有关
【解答】C
(13)下面关于哈希查找的说法,不正确的是( )。
A. 采用链地址法处理冲突时,查找一个元素的时间是相同的
B. 采用链地址法处理冲突时,若插入规定总是在链首,则插入任一个元素的时间是相同的
C. 用链地址法处理冲突,不会引起二次聚集现象
D. 用链地址法处理冲突,适合表长不确定的情况
【解答】A
在同义词构成的单链表中,查找该单链表表中不同元素,所消耗的时间不同 。
(14)设哈希表长为14,哈希函数是 H(key)=key%11,表中已有数据的关键字为15,38,61, 84 共四个,现要将关键字为49的元素加到表中,用二次探测法解决冲突,则放入的位置是( )。
A. 8 B. 3 C. 5 D. 9
【解答】D
关键字 15 放入位置 4,关键字 38 放入位置 5,关键字 61 放入位置 6,关键字 84放入位置 7,再添加关键字 49,计算得到地址为 5,冲突,用二次探测法解决冲突得到新地址为 6,仍冲突,再用用二次探测法解决冲突,得到新地址为 4,仍冲突,再用用二次探测法解决冲突,得到新地址为 9,不冲突,即将关键字 49 放入位置 9。
(15)采用线性探测法处理冲突,可能要探测多个位置,在查找成功的情况下,所探测的这些位置上的关键字( )。
A. 不一定都是同义词 B. 一定都是同义词 C. 一定都不是同义词 D. 都相同
【解答】A
所探测的这些关键字可能是在处理其它关键字冲突过程中放入该位置的。
2. 应用题
(1)假定对有序表:(3,4,5,7,24,30,42,54,63,72,87,95)进行折半查找,试回答下列问题。
① 画出描述折半查找过程的判定树;
② 若查找元素 54,需依次与哪些元素比较?
③ 若查找元素 90,需依次与哪些元素比较?
④ 假定每个元素的查找概率相等,求查找成功时的平均查找长度。
【解答】
① 画出描述折半查找过程的判定树
② 若查找元素 54,需依次与哪些元素比较?
若查找元素 54,需依次与30、63、42、54元素比较。
③ 若查找元素 90,需依次与哪些元素比较?
若查找元素 90,需依次与30、63、87、95元素比较。’
④ 假定每个元素的查找概率相等,求查找成功时的平均查找长度。
(2)在一棵空的二叉排序树中依次插入关键字序列为(12,7,17,11,16,2,13,9,21,4),请画出所得到的二叉排序树。
【解答】
二叉排序树:若它的左子树不空,则左子树上所有结点的值均小于它根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它根结点的值;它的左、右树又分为⼆叉排序树。
(3)已知如下所示长度为 12 的表(Jan, Feb, Mar, Apr, May, June, July, Aug, Sep, Oct, Nov, Dec)。
① 试按表中元素的顺序依次插入一棵初始为空的二叉排序树,画出插入完成之后的二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。
② 若对表中元素先进行排序构成有序表,求在等概率的情况下对此有序表进行折半查找时查找成功的平均查找长度。
③ 按表中元素顺序构造一棵平衡二叉排序树,并求其在等概率的情况下查找成功的平均查找长度。
【解答】
① 二叉排序树如下:
其平均查找长度 ASL = 1/12 (1*1+2*2+3*3+3*4+2*5+1*6) = 3.5。
② 经过排序后(通过字母先后)的有序表为:(8
折半查找:
故查找成功的平均查找长度为:
③ 平衡二叉树:每个子树的左右高度差都不超过一。
故查找成功的平均查找长度为:
(4)对图 7.31 所示的 3 阶 B- 树,依次执行下列操作,画出各步操作的结果。

① 插入90; ② 插入25; ③ 插入45; ④ 删除60。
【解答】
(5)设散列表的地址范围为 0 ~ 17,散列函数为 H(key) = key % 16。用线性探测法处理冲突,输入关键字序列 (10,24,32,17,31,30,46,47,40,63,49),构造散列表,试回答下列问题。
① 画出散列表的示意图;
② 若查找关键字 63,需要依次与哪些关键字进行比较?
③ 若查找关键字 60,需要依次与哪些关键字进行比较?
④ 假定每个关键字的查找概率相等,求查找成功时的平均查找长度。
【解答】
① 由题意,表长为18,即 m = 18,线性探测法,d = 1, 2, 3, ......, m-1。
② 若查找关键字 63,需要依次与哪些关键字进行比较
63 % 16 = 15,所以 63 要与地址 15 内存放的关键字进行比较,即 63 和 31 比较,不匹配,往后移(用线性探测法)。(15+1) % 18 = 16,依次类推,故要查找关键字 63,需要依次与 31、36、47、32、17、63 比较,一共 6 次比较。
③ 若查找关键字 60,需要依次与哪些关键字进行比较
与第二题类似,要查找关键字 60,60 % 16 = 12,所以 60 要与地址 12 内存放的关键字进行比较,而地址 12 存放的内容为空,即只需比较一次。
④ 评均查找长度
(6)设有一组关键字 (9,01,23,14,55,20,84,27),采用散列函数 H(key) = key % 7,表长为 10,用开放地址法的二次探测法处理冲突。要求:对该关键字序列构造散列表,并计算查找成功的平均查找长度。限定
取值为
。
【解答】
查找成功的平均查找长度为:
(7)设散列函数 H(K) = 3 K % 11,散列地址空间为 0 ~ 10,对关键字序列 (32,13,49,24, 38, 21, 4,12),按下述两种解决冲突的方法构造散列表,并分别求出等概率下查找成功时和查找失败时的平均查找长度
和
。
① 线性探测法。
② 链地址法。
【解答】
① 线性探测法。
② 链地址法。
3. 算法设计题
(1)试设计折半查找的递
折半查找 即 二分查找,查找过程:从中间记录开始,如果给定值和中间记录的关键字相等,则查找成功;如果大于或小于中间记录的关键字,则在大于或小于中间记录的那一半查找,直到查找成功。
【算法描述】
【完整代码】
【运算结果】
(2)试设计一个判别给定二叉树是否为二叉排序树的算法。
二叉排序树的定义:
(1)若它的左子树不空,则左子树上所有节点的值均小于它的根结点的值;
(2)若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
(3)它的左、右子树也分别为二叉排序树。
【算法描述】
【完整代码】
【运算结果】
(3)已知二叉排序树采用二叉链表存储结构,根结点的指针为 T,链节点的结构( lchild, data, rchild ),其中 lchild、rchild 分别指向该节点左、右孩子的指针,data 存放节点的数据信息。 请设计递归算法, 从小到大输出二叉排序树中所有数据值大于等于 x 的节点的数据。要求先找到第一个满足条件的节点后,再依次输出其他满足条件的节点。
【算法描述】
【完整代码】
【运算结果】
(4)已知二叉树 T 的节点形式为( lling,data,count,rlink ),在树中查找值为 X 的节点,若找到,则记数( count )加 1,否则,作为一个新节点插入树中,插入后仍为二叉排序树,设计其非递归算法。
【算法描述】
【完整代码】
【运算结果】
(5)假设一棵平衡二叉树的每个节点都表明了平衡因子 b,试设计一个算法,求平衡二叉树的高度。
平衡因子:该节点的左子树和右子树的深度之差(左 - 右),平衡因子只可能是 -1、0和1。
【算法描述】
【完整代码】
【运算结果】
(6)分别写出在散列表中插入和删除关键字为 K 的一个记录的算法,设散列函数为 H,解决冲突的方法为链地址法。
【算法描述】
【完整代码】
【运算结果】
第八章 排序
1. 选择题
(1)从未排序序列中依次取出元素与已排序序列中的元素进行比较, 将其放入已排序序
列的正确位置上的方法,这种排序方法称为( )。
A. 归并排序 B. 冒泡排序 C. 插入排序 D. 选择排序
【解答】C
(2)从未排序序列中挑选元素,并将其依次放入已排序序列(初始时为空)的一端的方
法,称为( )。
A. 归并排序 B. 冒泡排序 C. 插入排序 D. 选择排序
【解答】D
(3)对 n 个不同的关键字由小到大进行冒泡排序,在下列( )情况下比较的次数最多。
A. 从小到大排列好的 B. 从大到小排列好的 B. 元素无序 B. 元素基本有序
【解答】B
对关键字进行冒泡排序,关键字逆序时比较次数最多。
(4)对 n 个不同的排序码进行冒泡排序,在元素无序的情况下比较的次数最多为( ) 。
A. n+1 B. n B. n-1 B. n(n-1)/2
【解答】D
比较次数最多时,第一次比较 n-1 次,第二次比较 n-2 次, 最后一次比较 1 次,
即 (n-1) + (n-2) +......+ 1 = n(n-1)/2
(5)快速排序在下列( )情况下最易发挥其长处。
A. 被排序的数据中含有多个相同排序码
B. 被排序的数据已基本有序
B. 被排序的数据完全无序
B. 被排序的数据中的最大值和最小值相差悬殊
【解答】C
B 选项是快速排序的最坏情况。
(6)对 n 个关键字作快速排序,在最坏情况下,算法的时间复杂度是( )。
A. O(n) B. O(
) B. O(
) B. O(
)
【解答】B
快速排序的平均时间复杂度为 O() ,但在最坏情况下,即关键字基本排好
序的情况下,时间复杂度为 O()。
(7)若一组记录的排序码为( 46, 79 ,56 ,38 ,40 ,84),则利用快速排序的方法,以第一个记录为基准得到的一次划分结果为( )。
A. 38 , 40, 46, 56 , 79, 84
B. 40, 38, 46 , 79, 56 , 84
B. 40 , 38, 46 , 56, 79, 84
B. 40, 38, 46 , 84, 56 , 79
【解答】C
(8)下列关键字序列中,( )是堆。
A. 16 , 72, 31, 23 , 94, 53
B. 94, 23 , 31 , 72 , 16, 53
B. 16 , 53, 23 , 94, 31, 72
B. 16 , 23, 53 , 31, 94, 72
【解答】D
D 选项为小根堆
(9)堆是一种( )排序。
A. 插入 B. 选择 B. 交换 B. 归并
【解答】B
(10)堆的形状是一棵( )。
A. 二叉排序树 B. 满二叉树 B. 完全二叉树 B. 平衡二叉树
【解答】C
(11)若一组记录的排序码为( 46, 79,56 , 38, 40,84 ),则利用堆排序的方法建立的
初始堆为( )。
A. 79 , 46, 56, 38 , 40, 84
B. 84, 79, 56 , 38, 40 , 46
B. 84 , 79, 56 , 46, 40, 38
B. 84, 56, 79 , 40, 46 , 38
【解答】B
(12)下述几种排序方法中,要求内存最大的是( )。
A. 希尔排序 B. 快速排序 C. 归并排序 D. 堆排序
【解答】C
堆排序、希尔排序的空间复杂度为 O(1) ,快速排序的空间复杂度为 O(log 2n),
归并排序的空间复杂度为 O(n) 。
(13)下述几种排序方法中,( )是稳定的排序方法。
A. 希尔排序 B. 快速排序 C. 归并排序 D. 堆排序
【解答】C
不稳定排序有:希尔排序、简单选择排序、快速排序、堆排序。
稳定排序有:直接插入排序、折半插入排序、冒泡排序、归并排序、基数排序。
(14)数据表中有 10000 个元素,如果仅要求求出其中最大的 10 个元素,则采用( )算法最节省时间。
A. 冒泡排序 B. 快速排序 C. 简单选择排序 D. 堆排序
【解答】D
(15)下列排序算法中,( )不能保证每趟排序至少能将一个元素放到其最终的位置上。
A. 希尔排序 B. 快速排序 C. 冒泡排序 D. 堆排序
【解答】A
快速排序的每趟排序能将作为枢轴的元素放到最终位置。
冒泡排序的每趟排序能将最大或最小的元素放到最终位置。
堆排序的每趟排序能将最大或最小的元素放到最终位置。
2. 应用题
(1)设待排序的关键字序列为 {12,2,16,30,28,10,16* ,20,6,18} ,试分别写出使用以下排序方法,每趟排序结束后关键字序列的状态。
① 直接插入排序;
② 折半插入排序;
③ 希尔排序(增量选取 5、3和1);
④ 冒泡排序;
⑤ 快速排序;
⑥ 简单选择排序;
⑦ 堆排序;
⑧ 二路归并排序。
【解答】
① 直接插入排序;
初始关键字:(12),2,16,30,28,10,16* ,20,6,18
i = 1 :(2,12),16,30,28,10,16* ,20,6,18
i = 2 :(2,12,16),30,28,10,16* ,20,6,18
i = 3 :(2,12,16,30),28,10,16* ,20,6,18
i = 4 :(2,12,16,28,30),10,16* ,20,6,18
i = 5 :(2,10,12,16,28,30),16* ,20,6,18
i = 6 :(2,10,12,16,16*,28,30),20,6,18
i = 7 :(2,10,12,16,16*,20,28,30),6,18
i = 8 :(2,6,10,12,16,16*,20,28,30),18
i = 9 :(2,6,10,12,16,16*,18,20,28,30)
② 折半插入排序;
初始关键字:(12),2,16,30,28,10,16* ,20,6,18
i = 1 :(2,12),16,30,28,10,16* ,20,6,18
i = 2 :(2,12,16),30,28,10,16* ,20,6,18
i = 3 :(2,12,16,30),28,10,16* ,20,6,18
i = 4 :(2,12,16,28,30),10,16* ,20,6,18
i = 5 :(2,10,12,16,28,30),16* ,20,6,18
i = 6 :(2,10,12,16,16*,28,30),20,6,18
i = 7 :(2,10,12,16,16*,20,28,30),6,18
i = 8 :(2,6,10,12,16,16*,20,28,30),18
i = 9 :(2,6,10,12,16,16*,18,20,28,30)
③ 希尔排序(增量选取 5、3和1);
第一趟:10,2,16,6,18,12,16*,20,30,28 (增量选取5)
第二趟:6,2,12,10,18,16,16*,20,30,28 (增量选取3)
第三趟:2,6,10,12,16,16*,18,20,28,30 (增量选取1)
④ 冒泡排序;
初始关键字:12,2,16,30,28,10,16* ,20,6,18
第一趟: 2,12,16,28,10,16*,20,6,18,30
第二趟: 2,12,16,10,16*,20,6,18,28,30
第三趟: 2,12,10,16,16*,6,18,20,28,30
第四趟: 2,10,12,16,6,16*,18,20,28,30
第五趟: 2,10,12,6,16,16*,18,20,28,30
第六趟: 2,10,6,12,16,16*,18,20,28,30
第七趟: 2,6,10,12,16,16*,18,20,28,30
第八趟: 2,6,10,12,16,16*,18,20,28,30
⑤ 快速排序;
初始关键字:{ 12 2 16 30 28 10 16* 20 6 18 }
第一趟:{6 2 10 } 12 { 28 30 16* 20 16 18 }
第二趟:{2 } 6 { 10 } 12 { 28 30 16* 20 16 18 }
第三趟:2 6 10 12 { 18 16 16* 20 } 28 { 30 }
第四趟:2 6 10 12 { 16* 16 } 18 { 20 } 28 30
第五趟:2 6 10 12 16* { 16 } 18 20 28 30
⑥ 简单选择排序;
初始关键字: 12 2 16 30 28 10 16* 20 6 18
第一趟:(2) 12 16 30 28 10 16* 20 6 18
第二趟:(2 6) 16 30 28 10 16* 20 12 18
第三趟:(2 6 10) 30 28 16 16* 20 12 18
第四趟:(2 6 10 12) 28 16 16* 20 30 18
第五趟:(2 6 10 12 16) 28 16* 20 30 18
第六趟:(2 6 10 12 16 16*) 28 20 30 18
第七趟:(2 6 10 12 16 16* 18) 20 30 28
第八趟:(2 6 10 12 16 16* 18 20) 30 28
第九趟:(2 6 10 12 16 16* 18 20 28) 30
⑦ 堆排序;
初始关键字: 12 2 16 30 28 10 16* 20 6 18
第一趟: 18 12 16 2 28 10 16* 20 6 30
第二趟: 6 18 16 20 12 10 16* 2 28 30
第三趟: 2 6 16 18 12 10 16* 20 28 30
第四趟: 16* 2 16 6 12 10 18 20 28 30
第五趟: 10 6 16 2 12 16* 18 20 28 30
第六趟: 6 12 10 2 16 16* 18 20 28 30
第七趟: 2 6 10 12 16 16* 18 20 28 30
⑧ 二路归并排序。
初始关键字: 12 2 16 30 28 10 16* 20 6 18
第一趟: 2 12 16 30 10 28 16* 20 6 18
第二趟: 2 12 16 30 10 16* 20 28 6 18
第三趟: 2 10 12 16 16* 20 28 30 6 18
第四趟: 2 6 10 12 16 16* 18 20 28 30
(2)给出如下关键字序列{321,156,57,46,28,7,331,33,34,63},试按链式基数排序方法,列出每一趟分配和收集的过程。
【解答】
(3)对输入序列(101,51,19,61,3,71,31,17,19,100,55,20,9,30,50,6,90 );当 k = 6 时,使用置换 -- 选择算法,写出建立的初始败者树及生成的初始归并段。
【解答】
初始归并段::3,19,31,51,61,71,100,101
:9,17,19,20,30,50,55,90
:6
3. 算法设计题
(1)试以单链表为存储结构,实现简单选择排序算法。
【算法描述】
【完整代码】
【运算结果】
(2)有 n 个记录存储在带头节点的双向链表中, 利用双向冒泡排序法对其按上升序进行排序,请设计这种排序的算法。(注:双向冒泡排序即相邻两趟排序向相反方向冒泡。)
【算法描述】
【完整代码】
【运算结果】
(3)设有顺序放置的 n 个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排这些砾石,使得所有红色砾石在前,所有白色砾石居中,所有蓝色砾石居后,重新安排时对每粒砾石的颜色只能看一次,并且只允许交换操作来调整砾石的位置。
【算法描述】
【完整代码】
【运算结果】
(4)设计算法,整理对 n 个关键字取整数值的记录序列进行整理,以使所有关键字为负值的记录排在关键字为非负值的记录之前,要求:
① 采用顺序存储结构,至多使用一个记录的辅助存储空间;
② 算法的时间复杂度为 O(n)。
【算法描述】
【完整代码】
【运算结果】
(5)借助于快速排序的算法思想, 在一组无序的记录中查找给定关键字值等于 key 的记录。设此组记录存放于数组 r [ 1 … n ] 中。若查找成功,则输出该记录在 r 数组中的位置及其关键字值,否则显示“ not find ”信息。请简要说明算法思想并设计算法。
【算法描述】
【完整代码】
【运算结果】
(6)有一种简单的排序算法,叫做计数排序。这种排序算法对一个待排序的表进行排序,并将排序结果存放到另一个新的表中。必须注意的是,表中所有待排序的关键字互不相同,计数排序算法针对表中的每个记录,查找待排序的表一趟,统计表中有多少个记录的关键字比该记录的关键小。假设针对某一个记录,统计出的计数值为 c,那么,这个记录在新的有序表中的合适的存放位置即为 c。
① 给出适用于计数排序的顺序表定义;
② 设计实现计数排序的算法;
③ 对于有 n 个记录的表,关键字比较次数是多少?
④ 与简单选择排序相比较,这种方法是否更好?为什么?
【算法描述】
【完整代码】
【运算结果】
③ 对于有 n 个记录的表,关键字比较次数是多少?
外层循环遍历每个记录,执行 n 次。
内层循环对每个记录再次遍历整个表,执行 n 次。
则关键字比较的总次数为:
④ 与简单选择排序相比较,这种方法是否更好?为什么?
简单选择排序算法比本算法好。
简单选择排序比较次数是,且只用一个交换记录的空间;而这种方法比较次数是,且需要另一数组空间。