发布时间 : 星期一 文章数据结构课后习题答案详解(C语言版 - 严蔚敏) 2更新完毕开始阅读6d25520b02020740be1e9b14
数据结构习题集答案(C语言版严蔚敏) 第2章 线性表
2.1 描述以下三个概念的区别:头指针,头结点,首元结点(第一个元素结点)。
解:头指针是指向链表中第一个结点的指针。首元结点是指链表中存储第一个数据元素的结点。头结点是在首元结点之前附设的一个结点,该结点不存储数据元素,其指针域指向首元结点,其作用主要是为了方便对链表的操作。它可以对空表、非空表以及首元结点的操作进行统一处理。 2.2 填空题。
解:(1) 在顺序表中插入或删除一个元素,需要平均移动表中一半元素,具体移动的元素个数与元素在表中的位置有关。 (2) 顺序表中逻辑上相邻的元素的物理位置必定紧邻。单链表中逻辑上相邻的元素的物理位置不一定紧邻。 (3) 在单链表中,除了首元结点外,任一结点的存储位置由其前驱结点的链域的值指示。 (4) 在单链表中设置头结点的作用是插入和删除首元结点时不用进行特殊处理。 2.3 在什么情况下用顺序表比链表好?
解:当线性表的数据元素在物理位置上是连续存储的时候,用顺序表比用链表好,其特点是可以进行随机存取。 2.4 对以下单链表分别执行下列各程序段,并画出结果示意图。
解:
2.5 画出执行下列各行语句后各指针及链表的示意图。
L=(LinkList)malloc(sizeof(LNode)); P=L; for(i=1;i<=4;i++){ P->next=(LinkList)malloc(sizeof(LNode)); P=P->next; P->data=i*2-1; } P->next=NULL; for(i=4;i>=1;i--) Ins_LinkList(L,i+1,i*2); for(i=1;i<=3;i++) Del_LinkList(L,i); 解:
2.6 已知L是无表头结点的单链表,且P结点既不是首元结点,也不是尾元结点,试从下列提供的答案中选择合适的语句序列。
a. 在P结点后插入S结点的语句序列是__________________。 b. 在P结点前插入S结点的语句序列是__________________。 c. 在表首插入S结点的语句序列是__________________。 d. 在表尾插入S结点的语句序列是__________________。 (1) P->next=S;
(2) P->next=P->next->next; (3) P->next=S->next; (4) S->next=P->next; (5) S->next=L; (6) S->next=NULL; (7) Q=P;
(8) while(P->next!=Q) P=P->next; (9) while(P->next!=NULL) P=P->next; (10) P=Q; (11) P=L; (12) L=S; (13) L=P;
解:a. (4) (1) b. (7) (11) (8) (4) (1) c. (5) (12) d. (9) (1) (6)
2.7 已知L是带表头结点的非空单链表,且P结点既不是首元结点,也不是尾元结点,试从下列提供的答案中选择合适的语句序列。 a. 删除P结点的直接后继结点的语句序列是____________________。 b. 删除P结点的直接前驱结点的语句序列是____________________。 c. 删除P结点的语句序列是____________________。 d. 删除首元结点的语句序列是____________________。
1
e. 删除尾元结点的语句序列是____________________。 (1) P=P->next; (2) P->next=P;
(3) P->next=P->next->next; (4) P=P->next->next;
(5) while(P!=NULL) P=P->next;
(6) while(Q->next!=NULL) { P=Q; Q=Q->next; } (7) while(P->next!=Q) P=P->next;
(8) while(P->next->next!=Q) P=P->next; (9) while(P->next->next!=NULL) P=P->next; (10) Q=P;
(11) Q=P->next; (12) P=L;
(13) L=L->next; (14) free(Q);
解:a. (11) (3) (14) b. (10) (12) (8) (3) (14) c. (10) (12) (7) (3) (14) d. (12) (11) (3) (14) e. (9) (11) (3) (14)
2.8 已知P结点是某双向链表的中间结点,试从下列提供的答案中选择合适的语句序列。a. 在P结点后插入S结点的语句序列是_______________________。 b. 在P结点前插入S结点的语句序列是_______________________。 c. 删除P结点的直接后继结点的语句序列是_______________________。 d. 删除P结点的直接前驱结点的语句序列是_______________________。 e. 删除P结点的语句序列是_______________________。 (1) P->next=P->next->next; (2) P->priou=P->priou->priou; (3) P->next=S; (4) P->priou=S; (5) S->next=P; (6) S->priou=P;
(7) S->next=P->next; (8) S->priou=P->priou;
(9) P->priou->next=P->next; (10) P->priou->next=P; (11) P->next->priou=P; (12) P->next->priou=S; (13) P->priou->next=S;
(14) P->next->priou=P->priou; (15) Q=P->next; (16) Q=P->priou; (17) free(P); (18) free(Q);
解:a. (7) (3) (6) (12) b. (8) (4) (5) (13) c. (15) (1) (11) (18) d. (16) (2) (10) (18) e. (14) (9) (17) 2.9 简述以下算法的功能。
(1) Status A(LinkedList L) { //L是无表头结点的单链表 if(L && L->next) { Q=L; L=L->next; P=L; while(P->next) P=P->next; P->next=Q; Q->next=NULL; } return OK; }
(2) void BB(LNode *s, LNode *q) { p=s; while(p->next!=q) p=p->next; p->next =s; } void AA(LNode *pa, LNode *pb) { //pa和pb分别指向单循环链表中的两个结点 BB(pa,pb); BB(pb,pa); }
解:(1) 如果L的长度不小于2,将L的首元结点变成尾元结点。 (2) 将单循环链表拆成两个单循环链表。
2.10 指出以下算法中的错误和低效之处,并将它改写为一个既正确又高效的算法。 Status DeleteK(SqList &a,int i,int k) { //本过程从顺序存储结构的线性表a中删除第i个元素起的k个元素 if(i<1||k<0||i+k>a.length) return INFEASIBLE;//参数不合法 else {
for(count=1;count
2
} 解:
Status DeleteK(SqList &a,int i,int k) { //从顺序存储结构的线性表a中删除第i个元素起的k个元素 //注意i的编号从0开始 int j; if(i<0||i>a.length-1||k<0||k>a.length-i) return INFEASIBLE; for(j=0;j<=k;j++) a.elem[j+i]=a.elem[j+i+k]; a.length=a.length-k; return OK; }
2.11 设顺序表va中的数据元素递增有序。试写一算法,将x插入到顺序表的适当位置上,以保持该表的有序性。 解:
Status InsertOrderList(SqList &va,ElemType x) { //在非递减的顺序表va中插入元素x并使其仍成为顺序表的算法 int i; if(va.length==va.listsize)return(OVERFLOW); for(i=va.length;i>0,x A??a1,?,am?和B??b1,?,bn?均为顺序表,A?和 B?分别为A和 B中除去最大共同前缀后的子表。若 A??B??空表,则A?B;若A?=空表,而B??否则A?B。试写一个比较A,B大小的算法。 空表,或者两者均不为空表,且A?的首元小于B?的首元,则A?B; 解: Status CompareOrderList(SqList &A,SqList &B) { int i,k,j; k=A.length>B.length?A.length:B.length; for(i=0;i 2.13 试写一算法在带头结点的单链表结构上实现线性表操作Locate(L,x); 解: int LocateElem_L(LinkList &L,ElemType x) { int i=0; LinkList p=L; while(p&&p->data!=x){ p=p->next; i++; } if(!p) return 0; else return i; } 2.14 试写一算法在带头结点的单链表结构上实现线性表操作Length(L)。 解: //返回单链表的长度 int ListLength_L(LinkList &L) { int i=0; LinkList p=L; if(p) p=p-next; while(p){ p=p->next; i++; } return i; } 2.15 已知指针ha和hb分别指向两个单链表的头结点,并且已知两个链表的长度分别为m和n。试写一算法将这两个链表连接在一起,假设指针hc指向连接后的链表的头结点,并要求算法以尽可能短的时间完成连接运算。请分析你的算法的时间复杂度。 解: void MergeList_L(LinkList &ha,LinkList &hb,LinkList &hc) { LinkList pa,pb; pa=ha; pb=hb; while(pa->next&&pb->next){ pa=pa->next; 3 pb=pb->next; } if(!pa->next){ hc=hb; while(pb->next) pb=pb->next; pb->next=ha->next; } else{ hc=ha; while(pa->next) pa=pa->next; pa->next=hb->next; } } 2.16 已知指针la和lb分别指向两个无头结点单链表中的首元结点。下列算法是从表la中删除自第i个元素起共len个元素后,将它们插入到表lb中第i个元素之前。试问此算法是否正确?若有错,请改正之。 Status DeleteAndInsertSub(LinkedList la,LinkedList lb,int i,int j,int len) { if(i<0||j<0||len<0) return INFEASIBLE; p=la; k=1; while(knext; k++; } q=p; while(k<=len){ q=q->next; k++; } s=lb; k=1; while(k Status DeleteAndInsertSub(LinkList &la,LinkList &lb,int i,int j,int len) { LinkList p,q,s,prev=NULL; int k=1; if(i<0||j<0||len<0) return INFEASIBLE; // 在la表中查找第i个结点 p=la; while(p&&knext; k++; } if(!p)return INFEASIBLE; // 在la表中查找第i+len-1个结点 q=p; k=1; while(q&&k 2.17 试写一算法,在无头结点的动态单链表上实现线性表操作Insert(L,i,b),并和在带头结点的动态单链表上实现相同操作的算法进行比较。 2.18试写一算法,实现线性表操作Delete(L,i),并和在带头结点的动态单链表上实现相同操作的算法进行比较。 2.19 已知线性表中的元素以值递增有序排列,并以单链表作存储结构。试写一高效的算法,删除表中所有值大于mink且小于maxk的元素(若表中存在这样的元素),同时释放被删结点空间,并分析你的算法的时间复杂度(注意,mink和maxk是给定的两个参变量,它们的值可以和表中的元素相同,也可以不同)。 解: Status ListDelete_L(LinkList &L,ElemType mink,ElemType maxk) { LinkList p,q,prev=NULL; if(mink>maxk)return ERROR; p=L; prev=p; p=p->next; while(p&&p->data 4