第05讲 线性表的链式表示 课堂互动 隐藏答案 | 返回首页

作者:欧新宇(Xinyu OU)

最后更新:2023-09-14


【课前自测05】

1.(单选)线性表采用链式存储结构所具有的特点是()。
A. 所需空间地址必须不连
B. 需要事先估计所需存储空间
C. 可随机存取
D. 插入、删除操作不必移动元素

答案及解析:D
选项ABC是线性表顺序存储结构的特点。

2.(单选)顺序存储方式插入和删除时效率太低,因此它不如链式存储方式好。
A. 正确
B. 错误

答案及解析:B
不同的存储方式各有优劣,并没有绝对的好坏。例如,对于取值操作顺序存储优于链式存储,而删除、插入操作链式存储优于顺序存储。

3.(单选)对任何数据结构链式存储结构一定优于顺序存储结构。
A. 正确
B. 错误

答案及解析:B
不同的存储方式各有优劣,并没有绝对的好坏。例如,对于取值操作顺序存储优于链式存储,而删除、插入操作链式存储优于顺序存储。

4.(单选)为了很方便的插入和删除数据,可以使用双向链表存放数据。
A. 正确
B. 错误

答案及解析:A
在双向链表中,可以直接删除当前指针所指向的节点。而单向链表中,删除一个元素必须找到其前驱。因此在插入数据时,单向链表和双向链表操作复杂度相同。而删除数据时,双向链表的性能优于单向链表

5.(单选)线性表采用链表存储时,结点的存储空间可以是不连续的。
A. 正确
B. 错误

答案及解析:A
链表使用指针进行数据存储,因此链表的存储空间可以是不连续的。

6.(单选)‎关于线性表的顺序存储结构和链式存储结构的描述中,正确的是( )。
‎Ⅰ.线性表的顺序存储结构优于链式存储结构​
‎Ⅱ.顺序存储结构比链式存储结构的存储密度高​
‎Ⅲ.如需要频繁插入和删除元素,最好采用顺序存储结构​
‎Ⅳ.如需要频繁插入和删除元素,最好采用链式存储结构

A. Ⅰ、Ⅱ、Ⅲ
B. Ⅱ、Ⅳ
C. Ⅱ、Ⅲ
D. Ⅲ、Ⅳ

答案及解析:B
线性表的顺序存储结构和链式存储结构各有优缺点,不能简单比较好坏,所以Ⅰ错误。链式存储结构使用指针表示逻辑关系,所以存储密度比较低,所以Ⅱ正确。如频繁使用插入和删除操作,链式存储结构更优于顺序存储结构,所以Ⅲ错误,Ⅳ正确。

7.(单选)关于线性表的顺序存储结构和链式存储结构的描述中,正确的是( )。
I. 线性表的顺序存储结构优于其链式存储结构
II. 链式存储结构比顺序存储结构能更能方便地表示各种逻辑结构
III. 若频繁使用插入和删除结点操作,则顺序存储结构更由于链式存储结构
VI. 顺序存储结构和链式存结构都可以进行顺序存储

A. I、II、III
B. II、IV
C. II、III
D. III、IV

答案及解析:B
两种存储结构有不同的使用场合,不能简单地说谁好谁坏,I 错误。链式存储用指针表示逻辑结构,而指针的设置是任意的,故可以很方便地表示各种逻辑结构;顺序存储只能用物理上的邻接关系来表示逻辑结构,II 正确。在顺序存储中,插入和删除结点需要移动大量元素,效率低,III 的描述恰好相反。顺序存储结构技能随机存取又能顺序存取,而链式结构只能顺序存取不能随机存取,所以 VI 正确。

【课堂互动5.1】线性表的链式表示

‍1.(单选)在单链表中,增加一个头节点的目的是为了( )。
A. 使单链表至少有一个节点
B. 标识链表中某个重要节点的位置
C. 方便插入和删除运算的实现
D. 表示单链表是线性表的链式存储结构

答案及解析:C
单链表设置头结点的目的是方便运算的实现,如查找、插入、删除等。首先,有头结点后,插入和删除数据元素的算法就统一了,不再需要判断是否在第一个元素之前插入或删除第一个元素;第二,不论链表是否为空,其头结点是指向头结点的非空指针,链表的头指针不空,因此空表和非空表的处理就统一了。

2.(单选)已知表头元素为c的单链表在内存中的存储状态如下表所示。

地址 元素 链接地址
1000H a 1010H
1004H b 100CH
1008H c 1000H
100CH d Null
1010H e 1004H
1014H f -

现将 f 存放于1014H处并插入单链表,若 f 在逻辑上位于a和e之间,则 a,e,f 的链接地址分别为( )。
A. 1010H,1014H,1004H
B. 1010H,1004H,1014H
C. 1014H,1010H,1004H
D. 1014H,1004H,1010H

答案及解析:D
在本题中,“链接地址”是指结点Next指针所指向的内存地址,换句话说它是指当前结点所指向的下一个结点。现在将 f 存于 a 和 e 之间,这意味着这三个结点的顺序为 a,f,e。所以,a,e,f的链接地址就应该是f,b,e,所以选项D是正确的。

【课堂互动5.2】单链表

‍1.(单选)某算法在含有n(n≥1)个节点的单链表中查找值为x节点,其时间复杂度是( )。
A. O(log2n)O(log_2 n)
B. O(1)O(1)
C. O(n2)O(n^2)
D. O(n)O(n)

答案及解析:D
需要从首节点出发逐一查找每个节点。

‍2.(单选)在长度为n(n≥1)的单链表中删除尾节点的时间复杂度为( )。
A. O(1)O(1)
B. O(log2n)O(log_2 n)
C. O(n)O(n)
D. O(n2)O(n^2)

答案及解析:C
在长度为n(n≥1)的单链表中删除尾节点时,需要找倒数第2个节点,此时时间复杂度为O(n)。

3.(单选)​设线性表中有n个元素,以下运算中,( )在单链表上实现要比在顺序表上实现效率更高。
A. 删除指定位置元素的后一个元素
B. 在尾元素的后面插入一个新元素
C. 顺序输出前k个元素
D. 交换第i个元素和第n-i+1个元素的值(i=1,2,…,n)

答案及解析:A
在顺序表中插入元素和删除元素时需要移动较多元素,而在单链表上执行同样的操作不需要移动元素,只需修改相关节点的指针域。

‍4.(单选)以下关于单链表的叙述中正确的是( )。
‍Ⅰ.节点除自身信息外还包括指针域,存储密度小于顺序表‍
‍Ⅱ.找第i个节点的时间为O(1)‍
‍Ⅲ.在插入、删除运算时不必移动节点

A. 仅Ⅰ、Ⅱ
B. 仅Ⅱ、Ⅲ
C. 仅Ⅰ、Ⅲ
D. Ⅰ、Ⅱ、Ⅲ

答案及解析:C
单链表不具有随机存取特性,即不能在O(1)的时间内找到第i个节点。

5.(单选)​长度为 n 的有序单链表中插入一个新结点,并仍然保持有序的时间复杂度为()。
A. O(1)O(1)
B. O(n)O(n)
C. O(n2)O(n^2)
D. O(nlog2n)O(nlog_2 n)

答案及解析:B
设单链表递增有序,首先要在单链表中找到一个大于x的结点的直接前驱p,在p之后插入该结点。查找的时间复杂度为O(n),插入的时间复杂度为O(1),总时间复杂度为O(n)。

6.(单选)‌通过含有n(n≥1)个元素的数组a,采用头插法建立一个单链表L,则L中节点值的次序( )。
A. 与数组a的元素次序相同
B. 与数组a的元素次序相反
C. 与数组a的元素次序无关
D. 以上都不对

答案及解析:B
采用头插法建立单链表时,后面的节点插入到最前端,所以L的节点值次序与数组a的元素次序相反。

【课堂互动5.3】双向链表

1. 下面关于线性表的一些说法中,正确的是()。
A. 对一个设有头指针和尾指针的单链表执行删除最后一个元素的操作与链表长度无关
B. 线性表中每个元素都有一个直接前驱和一个直接后继
C. 为了方便插入和删除数据,可以使用双链表存放数据
D. 取线性表第 i 个元素的时间与 i 的大小有关

答案及解析:C
双链表能很方便地访问前驱和后继,故删除和插入数据较为方便,所以选项C正确。选项A显然错误。选项B中第一个元素和最后一个元素不满足题设要求。选项D未考虑顺序存储的情况。

2. 在双链表中向p所指的结点之前插入一个结点q的操作为()。
A. p->prior = q; q->next = p; p->prior->next = q; q->prior = p->prior;
B. q->prior = p->prior; p->prior->next = q; q->next = p; p->prior = q->next;
C. q->next = p; p->next = q; q->prior->next = q; q->next = p;
D. p->prior ->next = q; q->next = p; q->prior = p->prior; p->prior = q

答案及解析:D
为了在p之前插入结点q,可以将p的前一个结点的next域指向q,将q的next域指向p,将q的prior域指向p的前一个结点,将p的prior域指向q。因此只有选项D满足条件。

3. 在双向链表存储结构中,删除p所指的结点时必须修改指针()。
A. p->prior->next = p->next; p->next->prior = p->prior;
B. p->prior = p->prior->prior; p->prior->next = p;
C. p->next->prior = p; p->next = p->next->next;
D. p->next = p->prior->prior; p->prior = p->next->next;

答案及解析:A
选项B和D的第一项修改的都是结点p的指针,而删除p无需对其处理p本身;选项C,第一项将p的直接后继指向p本身,也非删除操作。正确的只有选项A。

4. 与单链表相比,双链表的优点之一是()。
A. 插入、删除操作更方便
B. 可以进行随机访问
C. 可以省略表头指针或表尾指针
D. 访问前后相邻结点更灵活

答案及解析:D
在插入和删除操作上,单链表和双链表都不用移动元素,都很方便,单双链表修改指针的操作更复杂,所以选项A错误。双链表中可以快速访问任何一个结点的前驱和后继结点,选项D正确。

5. 带头结点的双循环链表L为空的条件是()。
A. L->prior == L && L->next == NULL
B. L->prior == NULL && L->next == NULL
C. L->prior == NULL && L->next == L
D. L->prior == L && L->next == L

答案及解析:D
循环双链表L判空的条件是头结点(头指针)的prior和next域都指向它自身。

【课堂互动5.4】循环链表

1. 已知一个带有表头结点的双向循环链表L,节点结构为[prev|data|next],其中prev和next分别指向其直接前驱和直接后继结点的指针,先要删除指针p所指的结点,正确的语句是:()。
A. p->next->prev = p->prev; p->prev->next = p->prev; free(p);
B. p->next->prev = p->next; p->prev->next = p->next; free(p);
C. p->next->prev = p->next; p->prev->next = p->prev; free(p);
D. p->next->prev = p->prev; p->prev->next = p->next; free(p);

答案及解析:D
选项A第二句代码,相当于将p的前驱结点的后继指针指向其自身,错误;选项B和C的第一句代码,相当于将p后继结点的前驱指针指向其自身,错误。因此,只有D选项正确。

2. 已知头指针 h 指向一个带头结点的非空单循环链表,结点结构为[data|next],其中next是指向直接后继结点的指针,p是尾指针,q是临时指针。现要删除该链表的第一个元素,正确的语句序列是()。
A. h->next = h->next->next; q = h->next; free(q);
B. q = h->next; h->next = h->next->next; free(q);
C. q = h->next; h->next = q->next; if(p!=q) p = h; free(q);
D. q = h->next; h->next = q->next; if(p==q) p = h; free(q);

答案及解析:D
要删除头结点,首先需要将临时指针q指向要删除的结点,即q = h->next;接下来将头结点指要删除的结点的后一个结点,即 h->next = h->next->next或 h->next = q->next;之后,需要探测一下待删除结点是否是链表的尾结点,如果不是则忽略;如果是则需要将尾指针指向头结点,于是有 if(p==q) p=h; free(q);最后,释放被删除结点的内存空间。

3. 一个链表最常用的操作是在末尾插入结点和删除结点,则选用()最节省时间。
A. 带头结点的双循环链表
B. 单循环链表
C. 带尾指针的单循环链表
D. 单链表

答案及解析:A
在链表的末尾插入和删除一个结点时,需要修改其相邻结点的指针域。而寻找尾结点及尾结点的前驱结点时,只有带头结点的双循环链表所需要的时间最少。

4. 设对 n(n>1) 个元素的线性表的运算只有4种:删除第一个元素;删除最后一个元素;在第一个元素之前插入新元素;在最后一个元素之后插入新元素,则最好使用()。
A. 只有尾结点指针没有头结点指针的循环单链表
B. 只有尾结点指针没有头结点指针的非循环双链表
C. 只有头结点指针没有尾结点指针的循环双链表
D. 既有头结点指针又有尾结点指针的循环单链表

答案及解析:C
对于选项A,删除尾结点p时,需要找到p的前一个结点,时间复杂度为O(n)。对于选项B,删除首结点p时,需要找到p的结点,这里没有直接给出头结点指针,而通过尾结点的prior指针找到p结点的时间复杂度O(n)。对于选项D,删除尾结点p时,需要找到p的前一个结点,时间复杂度为O(n)。对于选项C,执行者4种算法的时间复杂度均为O(1)。

5. 一个链表最常用的操作时在最后一个元素后插入一个元素和删除一个元素,则选用()最节省时间。
A. 不带头结点的单循环链表
B. 双链表
C. 不带头结点且有尾指针的单循环链表
D. 单链表

答案及解析:C
对于选项A,在最后一个元素之后插入元素的情况与普通单链表相同,时间复杂度为O(n);而删除表中第一个元素时,为保持单循环链表的性质,需要先遍历整个链表找到尾结点,再做删除操作,时间复杂度为O(n)。对于选项B,双链表的情况与单链表的相同,一个是O(n), 一个是O(1)。对于选项C,与A的分析对比,有尾结点的指针,省去了遍历链表的过程,因此时间复杂度均为O(1)。对于选项D,要在最后一个元素之后插入一个元素,需要遍历整个链表才能找到插入位置,时间复杂度为O(n);删除第一个元素的时间复杂度为O(1)。

【课堂互动5.5】广义表和多重链表

1.(单选)广义表((a,b,c,d))的表尾是()。
A. a
B. ()
C. (a,b,c,d)
D. (b,c,d)

答案及解析:B
广义表的的的表头为一个子表,即(a,b,c,d);除表头外的其他元素为表尾,因此表尾为空表()。

2.(单选)设广义表 L=((a,b,c)),则L的长度和深度分别为()。
A. 1和1
B. 1和3
C. 1和2
D. 2和3

答案及解析:C
广义表的长度是指广义表中所包含元素的个数,深度是指广义表中括号的层数。根据定义,L的长度为1,深度为2。

3.(单选)设广义表L=(a,b,L),其深度是()。
A. 2
B. 3
C. 正无穷
D. 都不对

答案及解析:C
L是一个递归表,长度为3,L相当于一个无限的广义表L=(a,b(a,b(a,b,...))),深度是正无穷。

4.(单选)已知广义表A=((a,(b,c)), (a,(b,c),d)),则运算GetHead(GetHead(GetTail(A)))的结果是()。
A. a
B. (b,c)
C. (a, (b,c))
D. ()

答案及解析:A
GetTail(A) = ((a,(b,c),d))
GetHead(GetTail(A)) = (a,(b,c),d)
GetHead(GetHead(GetTail(L)) = a

5.(单选)设广义表 L=(a,b,(c,d),(e,(f,g))),则运算GetHead(GetTail(GetHead(GetTail(GetTail(L)))))的结果是()。
A. d
B. (d)
C. (e)
D. a

答案及解析:A
GetTail(L) = (b,(c,d),(e,(f,g)))
GetTail(GetTail(L)) = ((c,d),(e,(f,g)))
GetHead(GetTail(GetTail(L)) = (c,d)
GetTail(GetHead(GetTail(GetTail(L)))) = (d)
GetHead(GetTail(GetHead(GetTail(GetTail(L))))) = d

【扩展练习05】

1. 对于一个线性表,既要求能够进行较快速地插入和删除,又要求存储结构能反映数据之间的逻辑关系,则应该用()。
A. 顺序存储方式
B. 链式存储方式
C. 散列存储方式
D. 以上均可以

答案及解析:B
首先直接排除A和D。散列存储通过散列函数映射到物理空间,不能反映数据之间的逻辑关系,排除C。链式存储能方便地表示各种逻辑关系,且插入和删除操作的时间复杂度为O(1)。

2. 对于顺序存储的线性表,其算法时间复杂度为O(1)的运算应该是()。
A. 将 n 个元素从小到大排序
B. 删除第 i 个元素
C. 改变第 i 个元素的值
D. 在第 i 个元素后插入一个新元素

答案及解析:C
对 n 个元素进行排序的时间复杂度最小也要O(n),通常为 O(nlog2n)O(nlog_2 n)O(n2)O(n^2)。在顺序表中删除和插入元素都需要顺序移动元素,时间复杂度为O(n)。

3. 设线性表中有2n个元素,()在单链表上实现要比在顺序表上实现效率更高。
A. 删除所有值为x的元素
B. 在最后一个元素的后面插入一个新元素
C. 顺序输出前k个元素
D. 交换第i个元素和第2n-i-1个元素的值(i=0,...,n-1)

答案及解析:A
对于A,在单链表和顺序表上实现的时间复杂度都为O(n),但后者要移动很多元素,因此在单链表上实现效率要更高。对于B和D,显然顺序表的效率更高。选项C,两者无区别。

4. 在一个单链表中,已知q所指结点时p所指结点的前驱结点,若在q和p之间插入结点s,则执行()
A. s->next = p; p->next = s;
B. p->next = s->next; s->next = p;
C. q->next = s; s->next = p
D. p->next = s; s->next = q;

答案及解析:C
s插入后,q称为s的前驱,而p称为s的后继。选项C正确。

5. 给定有n个元素的一维数组,建立一个由单链表的最低时间复杂度是()。
A. O(1)O(1)
B. O(n)O(n)
C. O(n2)O(n^2)
D. O(nlog2n)O(nlog_2 n)

答案及解析:D
若先建立链表,然后依次插入建立有序表,则每插入一个元素就需要遍历链表寻找插入位置,即直接插入排序,时间复杂度为O(n2)O(n^2)。若先将数组排好虚,然后建立链表,建立链表的时间复杂度为O(n)O(n),数组排序的最好时间复杂度为O(nlog2n)O(nlog_2n),总时间复杂度为O(nlog2n)O(nlog_2n)

6. 将长度尾n的单链表链接在长度为m的单链表后面,其算法的时间复杂度采用大O形式表示应该是()。
A. O(1)O(1)
B. O(n)O(n)
C. O(m)O(m)
D. O(n+m)O(n+m)

答案及解析:C
先遍历长度为m的单链表,找到该单链表的尾结点,然后将其next域指向另一个单链表的首结点,其时间复杂度尾O(m)。

答案及解析:C
单链表设置头结点的目的是方便运算的实现,如查找、插入、删除等。首先,有头结点后,插入和删除数据元素的算法就统一了,不再需要判断是否在第一个元素之前插入或删除第一个元素;第二,不论链表是否为空,其头结点是指向头结点的非空指针,链表的头指针不空,因此空表和非空表的处理就统一了。

7. 在一个长度为n的带头结点的单链表h上,设有尾指针r,则执行()操作与链表的表长有关。
A. 删除单链表中的第一个元素
B. 删除单链表中的最后一个元素
C. 在单链表第一个元素前插入一个新元素
D. 在单链表最后一个元素后插入一个新元素

答案及解析:B
删除单链表的最后一个结点需置前驱结点的指针为Null,需要从头开始依次遍历找到该前驱结点,需要O(n)的时间,与表长有关。其他操作均与表长无关。

8. 对于一个头结点为head的带头结点的单链表,判定该表为空表的条件是()。
A. head == NULL
B. head->next == NULL
C. head->next == head
D. head != NULL

答案及解析:B

9. 对于一个不带头结点的单链表,判定空表的条件为()。
A. head == NULL
B. head->next == NULL
C. head->next == head
D. head != NULL

答案及解析:A

第05讲 线性表的链式表示 课堂互动 隐藏答案 | 返回首页