1、计算机学科专业基础综合数据结构-线性表(一)及答案解析(总分:104.00,做题时间:90 分钟)一、单项选择题(总题数:12,分数:24.00)1.线性表是( )。(分数:2.00)A.一个有限序列,可以为空B.一个有限序列,不可以为空C.一个无限序列,可以为空D.一个无限序列,不可以为空2.在一个长度为 n 的顺序表中删除第 i 个元素(0=i=n)时,需向前移动 _ 个元素。(分数:2.00)A.n-iB.n-i+1C.n-i-1Di3.在一个长度为 n 的顺序表中向第 i 个元素(0in+1)之前插入一个新元素时,需向后移动( )个元素。(分数:2.00)A.n-iB.n-i+1C.n
2、-i-1Di4.下述哪一条是顺序存储结构的优点? _(分数:2.00)A.存储密度大B.插入运算方便C.删除运算方便D.可方便地用于各种逻辑结构的存储表示5.下面关于线性表的叙述中,错误的是哪一个? _(分数:2.00)A.线性表采用顺序存储,必须占用一片连续的存储单元B.线性表采用顺序存储,便于进行插入和删除操作C.线性表采用链接存储,不必占用一片连续的存储单元D.线性表采用链接存储,便于插入和删除操作6.若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用 _ 存储方式最节省时间。(分数:2.00)A.顺序表B.双链表C.带头结点的双循环链表D.单循环链表7.对
3、于顺序存储的线性表,访问结点和增加、删除结点的时间复杂度为 _ 。(分数:2.00)A.O(n),O(n)B.O(n),O(1)C.O(1),O(n)D.O(1),O(1)8.(1)静态链表既有顺序存储的优点,又有动态链表的优点,所以,它存取表中第 i 个元素的时间与 i 无关。(2)静态链表中能容纳的元素个数的最大数在表定义时就确定了,以后不能增加。(3)静态链表与动态链表在元素的插入、删除上类似,不需做元素的移动。以上错误的是 _ 。(分数:2.00)A.(1),(2)B.(1)C.(1),(2),(3)D.(2)9.某线性表中最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素,
4、则采用 _ 存储方式最节省运算时间。(分数:2.00)A.单链表B.仅有头指针的单循环链表C.双链表D.仅有尾指针的单循环链表10.在双向循环链表中,在 P 所指的结点之后插入 S 指针所指的结点,其操作是 _ 。(分数:2.00)A.pnext=s;sprior=p;pnextprior=s;snext=pnext;B.sprior=p;snext=pnext;pnext=s;Pnextprior=s:C.pnext=s;pnextprior=s;sprior=p;snext=pnext;D.sprior=p;snext=pnext;pnextprior=s;pnext=s:11.若长度为
5、n 的线性表采用顺序存储结构,在其第 i 个位置插入一个新元素的算法的时间复杂度为 _ (1=i=n+1)。 A.O(0) B.O(1) C.O(n) D.O(n2)(分数:2.00)A.B.C.D.12.设单链表中结点的结构为 typedef struct node链表结点定义 ElemType data; 数据 struct node*Link; 结点后继指针 ListNode; 已知指针 p 所指结点不是尾结点,若在 p 之后插入结点 s,则应执行下列哪一个操作? _(分数:2.00)A.slinkp;plinks;B.slinkplink;plinks;C.s 一link=Plink;
6、PS;D.plinkS;slinkp;二、综合应用题(总题数:8,分数:80.00)13.设计在无头结点的单链表中删除第 i 个结点的算法。 (分数:10.00)_14.设计将带表头的链表逆置算法。 (分数:10.00)_15.设顺序表中的数据元素递增有序,编写一算法将元素 X 插入到顺序表的适当位置上,并保证该表的有序性。 (分数:10.00)_16.设线性表 A=(a 1 ,a 2 ,a 3 ,a n )以带头结点的单链表作为存储结构。编写一个函数,对 A 进行调整,使得当 n 为奇数时 A=(a 2 ,a 4 ,a n-1 ,a 1 ,a 3 ,a n ),当 n 为偶数时 A=(a 2
7、 ,a 4 ,a n ,a 1 ,a 3 ,a n-1 )。 (分数:10.00)_17.试分别用顺序表和单链表作为存储结构,实现将线性表(a 0 ,a 1 ,a 2 ,a n-1 )就地逆置的操作,所谓“就地”,是指辅助空间应为 O(1)。 (分数:10.00)_18.假设以带头结点的单链表表示有序表,单链表的类型定义如下: typedef struct node DataType data: struct node *next LinkNode, *LinkList; 编写算法,从有序表 A 中删除所有和有序表 B 中元素相同的结点。 (分数:10.00)_19.设带表头结点的双向链表的定
8、义为 typedef int ElemType; typedef struct dnode双向链表结点定义 ElemType data;数据 struct dnode*lLink,*rLink;结点前驱与后继指针 )DblNode; typedef DblNode*DblList;双向链表 试设计一个算法,改造一个带表头结点的双向链表,所有结点的原有次序保持在各个结点的右链域 rLink中,并利用左链域 lLink 把所有结点按照其值从小到大的顺序连接起来。 (分数:10.00)_20.已知 L1、L2 分别为两循环单链表的头结点指针,m,n 分别为 L1、L2 表中数据结点个数。要求设计一算
9、法,用最快速度将两表合并成一个带头结点的循环单链表。 (分数:10.00)_计算机学科专业基础综合数据结构-线性表(一)答案解析(总分:104.00,做题时间:90 分钟)一、单项选择题(总题数:12,分数:24.00)1.线性表是( )。(分数:2.00)A.一个有限序列,可以为空 B.一个有限序列,不可以为空C.一个无限序列,可以为空D.一个无限序列,不可以为空解析:线性表是由相同类型的结点组成的有限序列。如:由 n 个结点组成的线性表 (a 1 ,a 2 ,a n ) a 1 是最前结点,a n 是最后结点。结点也称为数据元素或者记录。 线性表中结点的个数称为其长度。长度为 O 的线性表
10、称为空表。 所以答案为 A。2.在一个长度为 n 的顺序表中删除第 i 个元素(0=i=n)时,需向前移动 _ 个元素。(分数:2.00)A.n-i B.n-i+1C.n-i-1Di解析:一般情况下,删除顺序表的第 i(1-i-n)个元素时需要将第 i+1 到第 n 个元素(共 n-i 个元素)依次向前移动一个位置。所以答案为 A。3.在一个长度为 n 的顺序表中向第 i 个元素(0in+1)之前插入一个新元素时,需向后移动( )个元素。(分数:2.00)A.n-iB.n-i+1 C.n-i-1Di解析:一般情况下,在顺序表的第 i(1=i=n)个元素之前插入一个元素,需要将第 n 至 i 的
11、元素(共 n-i+1 个元素)向后移动一个位置。所以答案为 B。4.下述哪一条是顺序存储结构的优点? _(分数:2.00)A.存储密度大 B.插入运算方便C.删除运算方便D.可方便地用于各种逻辑结构的存储表示解析:顺序存储利用物理的邻接关系表示数据元素之间的逻辑关系,因此没有必要设置指针域,所以其存储密度比链式存储大,但是插入运算和删除运算都需大量移动数据元素,并不方便;D 选项并不是顺序存储结构的优点。所以答案为 A。5.下面关于线性表的叙述中,错误的是哪一个? _(分数:2.00)A.线性表采用顺序存储,必须占用一片连续的存储单元B.线性表采用顺序存储,便于进行插入和删除操作 C.线性表采
12、用链接存储,不必占用一片连续的存储单元D.线性表采用链接存储,便于插入和删除操作解析:线性表采用顺序存储,并不便于进行插入和删除操作。6.若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用 _ 存储方式最节省时间。(分数:2.00)A.顺序表 B.双链表C.带头结点的双循环链表D.单循环链表解析:“存取任一指定序号”最好的方法是实现“随机存取”,则可采用顺序表。并且,因为插入和删除操作都是在最后进行的,所以无需大量移动数据元素,选项 A 是最合适的。7.对于顺序存储的线性表,访问结点和增加、删除结点的时间复杂度为 _ 。(分数:2.00)A.O(n),O(n)B.
13、O(n),O(1)C.O(1),O(n) D.O(1),O(1)解析:顺序存储可以实现“随机存取”,因此访问结点的时间复杂度为 O(1),而插入、删除结点由于涉及到大量移动元素,故其时间复杂度为 O(n)。8.(1)静态链表既有顺序存储的优点,又有动态链表的优点,所以,它存取表中第 i 个元素的时间与 i 无关。(2)静态链表中能容纳的元素个数的最大数在表定义时就确定了,以后不能增加。(3)静态链表与动态链表在元素的插入、删除上类似,不需做元素的移动。以上错误的是 _ 。(分数:2.00)A.(1),(2)B.(1) C.(1),(2),(3)D.(2)解析:静态链表使用结构体数组来实现线性链
14、表的功能。因为其用游标 cur 来指示下一个数据元素的存储位置,所以存取数据时静态链表同线性链表(单链表)是相似的。也就是说,静态链表在存取表中第 i 个元素的时间同 i 是相关的。9.某线性表中最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素,则采用 _ 存储方式最节省运算时间。(分数:2.00)A.单链表B.仅有头指针的单循环链表C.双链表D.仅有尾指针的单循环链表 解析:仅有尾指针的单循环链表,可以非常方便地找到尾结点,尾结点后面的第一个结点往往是头结点,头结点的下一个结点就是第线性表的第一个结点。对最后一个元素和第一个元素操作对带尾指针的单循环链表是非常方便的。10.在双向
15、循环链表中,在 P 所指的结点之后插入 S 指针所指的结点,其操作是 _ 。(分数:2.00)A.pnext=s;sprior=p;pnextprior=s;snext=pnext;B.sprior=p;snext=pnext;pnext=s;Pnextprior=s:C.pnext=s;pnextprior=s;sprior=p;snext=pnext;D.sprior=p;snext=pnext;pnextprior=s;pnext=s: 解析:同单链表相比,双向链表的插入、删除操作需同时修改两个指针。 11.若长度为 n 的线性表采用顺序存储结构,在其第 i 个位置插入一个新元素的算法的
16、时间复杂度为 _ (1=i=n+1)。 A.O(0) B.O(1) C.O(n) D.O(n2)(分数:2.00)A.B.C. D.解析:顺序存储的线性表在插入新元素时,需要将第 i 个元素到第 n 个元素均向后移动一个单位,插入的新元素成为第 i 个元素,原来的第 i 个元素成为第 i+1 个元素,原来的第 n 个元素成为第 n+1 个元素,线性表的长度加 1,插入操作的主要工作都放在移动元素上。假设线性表中含有 n 个数据元素,在进行插入操作时,若假定在 n+1 个位置上插入元素的可能性均等,则平均移动元素的个数为:除非插入在线性表的最后,否则都要移动元素。所以其时间复杂度为 O(n),答
17、案为 C。12.设单链表中结点的结构为 typedef struct node链表结点定义 ElemType data; 数据 struct node*Link; 结点后继指针 ListNode; 已知指针 p 所指结点不是尾结点,若在 p 之后插入结点 s,则应执行下列哪一个操作? _(分数:2.00)A.slinkp;plinks;B.slinkplink;plinks; C.s 一link=Plink;PS;D.plinkS;slinkp;解析:二、综合应用题(总题数:8,分数:80.00)13.设计在无头结点的单链表中删除第 i 个结点的算法。 (分数:10.00)_正确答案:()解析
18、:算法思想为: (1)应判断删除位置的合法性,当 i0 或 in-1 时,不允许进行删除操作; (2)当 i=0 时,删除第一个结点; (3)当 0in 时,允许进行删除操作,但在查找被删除结点时,须用指针记住该结点的前趋结点。算法描述如下: delete(LinkList*q,int i) 在无头结点的单链表中删除第 i 个结点 LinkList *P,*S; int j; if(i0) printf(“Can“t delete”); else if(i=0) s=q; q=qnext; free(s); else j=0;s=q; while(ji)&(s!=NULL) p=s; s=s=
19、next; j+: if(s=NULL) printf(“Cant“t delete”); else pnext=snext; free(s); 14.设计将带表头的链表逆置算法。 (分数:10.00)_正确答案:()解析:解析:设单循环链表的头指针为 head,类型为 LinkList。逆置时需将每一个结点的指针域做一修改,使其原前趋结点成为后继。如要更改 q 结点的指针域时,设 S 指向其原前趋结点,P 指向其原后继结点,则只需进行 qnexts;操作即可,算法描述如下: void invert(LinkList*head) 逆置 head 指针所指向的单循环链表 linklist*p,*
20、q,*S; q=he ad;pheadnext;while(p!=head) 当表不为空时,逐个结点逆置 s=q;q=P;p=pnext;qnext=s;pnext=q;,15.设顺序表中的数据元素递增有序,编写一算法将元素 X 插入到顺序表的适当位置上,并保证该表的有序性。 (分数:10.00)_正确答案:()解析:只要从终端结点开始往前找到第一个比 X 小(或相等)的结点数据,在这个位置插入就可以了。算法描述如下: SqList*InsertSqList(SqList*L,int i,Elemtype x) if(i1)(iLlength+1) printf(“插入位置不合理”);exit
21、(l); if(LlengthLMaxSize1) print(“顺序表已满,不能再插入!”);exit(l); or(mLlength1;m=i1;m) Ldatam+1=Ldatam; Ldatai1=x; Llength+: return L; 16.设线性表 A=(a 1 ,a 2 ,a 3 ,a n )以带头结点的单链表作为存储结构。编写一个函数,对 A 进行调整,使得当 n 为奇数时 A=(a 2 ,a 4 ,a n-1 ,a 1 ,a 3 ,a n ),当 n 为偶数时 A=(a 2 ,a 4 ,a n ,a 1 ,a 3 ,a n-1 )。 (分数:10.00)_正确答案:()
22、解析:方法一: void f(LinkList L) LinkList p,q,r; p=L;*P 是偶数尾结点 q=Lnext;*q 是当前奇数结点 while(q&qnext)尚有未调整的偶数结点 r=qnext;r 指向当前偶数结点 qnext=rnext;删除偶数结点 rnext=Pnext。 Pnext=r; 插入偶数结点 p=pnext; q=qnext; 方法二: void f(LinkList L) LinkList p,h,r,s; if(!Lnext !Lnextnext)return; h=Lnext; r=h;h 和 r 分别为奇数结点的头、尾指针 Lnext=hnex
23、t; p=Lnext;p 指向偶数结点 while(pnext)2 个结点以上 s=pnext;s 指向奇数结点 pnext=snext;删除奇数结点 rnext=s;链接奇数结点 r=s: if(pnext) p=pnext;尚有偶数结点存在 pnext=h; rnext=NULL; 方法三: void f(LinkList L) LinkList p,h,rl,r2,s; if(!Lnext !Lnextnext)return; h=Lnext;h 是奇数结点头指针 r2=h;r2 是奇数尾结点指针 r1=L;r1 是偶数结点指针 p=hnext;p 指向第 1 个偶数结点 while(p
24、) s=pnext;s 指向下一个奇数结点 r1next=P; r1=P;链接偶数结点 if(s) p=snext;p 指向下一个偶数结点 r2next=s: r2=s;链接奇数结点 else p=s;偶数个数情况 r1next=h: r2next=NULL: 17.试分别用顺序表和单链表作为存储结构,实现将线性表(a 0 ,a 1 ,a 2 ,a n-1 )就地逆置的操作,所谓“就地”,是指辅助空间应为 O(1)。 (分数:10.00)_正确答案:()解析:方法一:用顺序表作存储结构 struct SqList/ ElemType*elem;存储空间基址 int length;当前长度 ;
25、void InvertSqList(SqListL) int i;ElemType temp; for(i0;iLlength/2;i+) temp=Lelem; Lelem=LelemL1engthi1; L.elemL.lengthi1temp; 方法二:用顺序表作存储结构 void InvertSqList(SqList&L)6 R int i,j;ElemType temp; i=0;j=Llength1; while(ij) temp=Lelem; Lelem=L.elemj L.elemj=temp i+;j; 方法三:用带头结点的单链表作存储结构 struct LNode Ele
26、mType data; LNode*next: ; typedef LNode*LinkList; Void InvertLinkList(LinkList&L) pL;LNULL; while(p) sp;ppnext; SnextL: 18.假设以带头结点的单链表表示有序表,单链表的类型定义如下: typedef struct node DataType data: struct node *next LinkNode, *LinkList; 编写算法,从有序表 A 中删除所有和有序表 B 中元素相同的结点。 (分数:10.00)_正确答案:()解析:void deleted_list(L
27、inkList A,LinkList B) LinkList p,q,r; r=A: p=Anext; q=Bnext; while(p!NULL&q!=NULL) if(pdataqdata) q=qnext else if(pdataqdata) r=P: ppnext; else rnext=pnext; free(p); p=rnext: 19.设带表头结点的双向链表的定义为 typedef int ElemType; typedef struct dnode双向链表结点定义 ElemType data;数据 struct dnode*lLink,*rLink;结点前驱与后继指针 )D
28、blNode; typedef DblNode*DblList;双向链表 试设计一个算法,改造一个带表头结点的双向链表,所有结点的原有次序保持在各个结点的右链域 rLink中,并利用左链域 lLink 把所有结点按照其值从小到大的顺序连接起来。 (分数:10.00)_正确答案:()解析:void sort(DblNode*L) DblNode*S=Lrlink;指针 s 指向待插入结点,初始时指向第一个结点 while(S!一 NULL)处理所有结点 pre=L; p=LlLink;指针 P 指向待比较的结点,pre 是 P 的前驱指针 while(p!NULL&sdatapdata) 循 1
29、Link 链寻找结点*S 的插入位置 pre=P; p=plLink; prelLink=S; sILink=p; ssrLink;结点*s 在 lLink 方向插入到*pre 与*p 之间 20.已知 L1、L2 分别为两循环单链表的头结点指针,m,n 分别为 L1、L2 表中数据结点个数。要求设计一算法,用最快速度将两表合并成一个带头结点的循环单链表。 (分数:10.00)_正确答案:()解析:循环单链表 L1 和 L2 数据结点个数分别为 m 和 n,将二者合成一个循环单链表时,需要将一个循环链表的结点(从第一元素结点到最后一个结点)插入到另一循环链表的第一元素结点前即可。题目要求“用最
30、快速度将两表合并”,因此应找结点个数少的链表查其尾结点。 LinkedList Union(LinkedList L1,L2;int m,n) L1 和 L2 分别是两循环单链表的头结点的指针,m 和 n 分别是 L1 和 L2 的长度。 本算法用最快速度将 L1 和 L2 合并成一个循环单链表。 if(m0 nO) printf(“表长输入错误/n”); exit(0); if(mn)若 mn,则查 L1 循环单链表的最后一个结点 if(m=0) return(L2);L1 为空表 else p=L1: while(pnext!L1) p=pnext;查最后一个元素结点 pnext=L2next; 将 L1 循环单链表的元素结点插入到 L2 的第一元素结点前 L2nextL1next; free(L1);释放无用头结点 处理完 mn 情况 else下面处理 L2 长度小于等于 L1 的情况 if(n=0) return(L1);L2 为空表 else pL2; while(pnext!L2) ppnext;查最后元素结点 PnextL1next; 将 L2 的元素结点插入到 L1 循环单链表的第一元素结点前 L1nextL2next; free(L2);释放无用头结点