1、1说明: 1. 本文是对严蔚敏数据结构(c 语言版)习题集一书中所有算法设计题目的解决方案,主要作者为 计算机版版主一具.以下网友:siice,龙抬头,iamkent,zames,birdthinking 等为答案的修订和完善工作提出了宝贵意见,在此表示感谢;2. 本解答中的所有算法均采用类 c 语言描述,设计原则为面向交流、面向阅读,作者不保证程序能够上机正常运行(这种保证实际上也没有任何意义);3. 本解答原则上只给出源代码以及必要的注释,对于一些难度较高或思路特殊的题目将给出简要的分析说明,对于作者无法解决的题目将给出必要的讨论.目前尚未解决的题目有: 5.20, 10.40;4. 请
2、读者在自己已经解决了某个题目或进行了充分的思考之后,再参考本解答,以保证复习效果;5. 由于作者水平所限,本解答中一定存在不少这样或者那样的错误和不足,希望读者们在阅读中多动脑、勤思考,争取发现和纠正这些错误,写出更好的算法来.请将你发现的错误或其它值得改进之处向作者报告: yi- 第一章 绪论 1.16 void print_descending(int x,int y,int z)/按从大到小顺序输出三个数scanf(“%d,%d,%d“,if(xy; /为表示交换的双目运算符,以下同if(yz;if(xy; /冒泡排序printf(“%d %d %d“,x,y,z);/print_des
3、cending 1.17 Status fib(int k,int m,int if(ka.length) return INFEASIBLE;for(count=1;i+count-1va.listsize) return ERROR;va.length+;for(i=va.length-1;va.elemixi-)va.elemi+1=va.elemi;va.elemi+1=x;return OK;/Insert_SqList 2.12 int ListComp(SqList A,SqList B)/比较字符表 A 和 B,并用返回值表示结果,值为正,表示 AB;值为负,表示 Anext;
4、pp=p-next);return p;/Locate 2.14 4int Length(LinkList L)/求链表的长度for(k=0,p=L;p-next;p=p-next,k+);return k;/Length 2.15 void ListConcat(LinkList ha,LinkList hb,LinkList p=ha;while(p-next) p=p-next;p-next=hb;/ListConcat 2.16 见书后答案. 2.17 Status Insert(LinkList q=(LinkList*)malloc(sizeof(LNode);q.data=b;i
5、f(i=1)q.next=p;L=q; /插入在链表头部elsewhile(-i1) p=p-next;q-next=p-next;p-next=q; /插入在第 i 个元素的位置/Insert 2.18 Status Delete(LinkList /删除第一个元素elsep=L;while(-i1) p=p-next;p-next=p-next-next; /删除第 i 个元素/Delete 2.19 Status Delete_Between(Linklist while(p-next-datanext; /p 是最后一个不大于 mink 的元素if(p-next) /如果还有比 min
6、k 更大的元素q=p-next;while(q-datanext; /q 是第一个不小于 maxk 的元素5p-next=q;/Delete_Between 2.20 Status Delete_Equal(Linklist q=p-next; /p,q 指向相邻两元素while(p-next)if(p-data!=q-data)p=p-next;q=p-next; /当相邻两元素不相等时,p,q 都向后推一步elsewhile(q-data=p-data) free(q);q=q-next; p-next=q;p=q;q=p-next; /当相邻元素相等时删除多余元素/else/while/
7、Delete_Equal 2.21 void reverse(SqList iA.elemj;/reverse 2.22 void LinkList_reverse(Linklist 为简化算法,假设表长大于2p=L-next;q=p-next;s=q-next;p-next=NULL;while(s-next)q-next=p;p=q;q=s;s=s-next; /把 L 的元素逐个插入新表表头q-next=p;s-next=q;L-next=s;/LinkList_reverse分析:本算法的思想是,逐个地把 L 的当前元素 q 插入新的链表头部,p 为新表表头. 2.23 void me
8、rge1(LinkList q=B-next;C=A;while(pp-next=q; /将 B 的元素插入if(s)6t=q-next;q-next=s; /如 A 非空,将 A 的元素插入p=s;q=t;/while/merge1 2.24 void reverse_merge(LinkList pb=B-next;pre=NULL; /pa 和 pb 分别指向 A,B 的当前元素while(pa|pb)if(pa-datadata|!pb)pc=pa;q=pa-next;pa-next=pre;pa=q; /将 A 的元素插入新表elsepc=pb;q=pb-next;pb-next=p
9、re;pb=q; /将 B 的元素插入新表pre=pc;C=A;A-next=pc; /构造新表头/reverse_merge分析:本算法的思想是,按从小到大的顺序依次把 A 和 B 的元素插入新表的头部 pc 处,最后处理 A 或 B 的剩余元素. 2.25 void SqList_Intersect(SqList A,SqList B,SqList j=1;k=0;while(A.elemiif(A.elemi=B.elemj)C.elem+k=A.elemi; /当发现了一个在 A,B 中都存在的元素,i+;j+; /就添加到 C 中/while/SqList_Intersect 2.2
10、6 void LinkList_Intersect(LinkList A,LinkList B,LinkList q=B-next;pc=(LNode*)malloc(sizeof(LNode);while(pelse if(p-dataq-data) q=q-next;elses=(LNode*)malloc(sizeof(LNode);s-data=p-data;7pc-next=s;pc=s;p=p-next;q=q-next;/whileC=pc;/LinkList_Intersect 2.27 void SqList_Intersect_True(SqList j=1;k=0;whi
11、le(A.elemielse if(A.elemi!=A.elemk)A.elem+k=A.elemi; /当发现了一个在 A,B 中都存在的元素i+;j+; /且 C 中没有,就添加到 C 中/whilewhile(A.elemk) A.elemk+=0;/SqList_Intersect_True 2.28 void LinkList_Intersect_True(LinkList q=B-next;pc=A;while(pelse if(p-dataq-data) q=q-next;else if(p-data!=pc-data)pc=pc-next;pc-data=p-data;p=p
12、-next;q=q-next;/while/LinkList_Intersect_True 2.29 void SqList_Intersect_Delete(SqList j=0;k=0;m=0; /i 指示 A 中元素原来的位置,m 为移动后的位置while(iC.elemk) k+;elsesame=B.elemj; /找到了相同元素 samewhile(B.elemj=same) j+;while(C.elemk=same) k+; /j,k 后移到新的元素while(inext;q=C-next;r=A-next;while(pelse if(p-dataq-data) q=q-ne
13、xt;elseu=p-data; /确定待删除元素 uwhile(r-next-datanext; /确定最后一个小于 u 的元素指针 rif(r-next-data=u)s=r-next;while(s-data=u)t=s;s=s-next;free(t); /确定第一个大于 u 的元素指针 s/whiler-next=s; /删除 r 和 s 之间的元素/ifwhile(p-data=u) p=p-next;while(q-data=u) q=q-next;/else/while/LinkList_Intersect_Delete 2.31 Status Delete_Pre(CiLNo
14、de *s)/删除单循环链表中结点 s 的直接前驱p=s;while(p-next-next!=s) p=p-next; /找到 s 的前驱的前驱 pp-next=s;return OK;/Delete_Pre 2.32 Status DuLNode_Pre(DuLinkList !p-next-pre;p=p-next) p-next-pre=p;return OK;/DuLNode_Pre 2.33 Status LinkList_Divide(LinkList 9A=(CiList*)malloc(sizeof(CiLNode);p=A;B=(CiList*)malloc(sizeof(
15、CiLNode);q=B;C=(CiList*)malloc(sizeof(CiLNode);r=C; /建立头结点while(s)if(isalphabet(s-data)p-next=s;p=s;else if(isdigit(s-data)q-next=s;q=s;elser-next=s;r=s;/whilep-next=A;q-next=B;r-next=C; /完成循环链表/LinkList_Divide 2.34 void Print_XorLinkedList(XorLinkedList L)/从左向右输出异或链表的元素值p=L.left;pre=NULL;while(p)pr
16、intf(“%d“,p-data);q=XorP(p-LRPtr,pre);pre=p;p=q; /任何一个结点的 LRPtr 域值与其左结点指针进行异或运算即得到其右结点指针/Print_XorLinkedList 2.35 Status Insert_XorLinkedList(XorLinkedList pre=NULL;r=(XorNode*)malloc(sizeof(XorNode);r-data=x;if(i=1) /当插入点在最左边的情况p-LRPtr=XorP(p.LRPtr,r);r-LRPtr=p;L.left=r;return OK;j=1;q=p-LRPtr; /当插
17、入点在中间的情况while(+jLRPtr,pre);pre=p;p=q;/while /在 p,q 两结点之间插入if(!q) return INFEASIBLE; /i 不可以超过表长p-LRPtr=XorP(XorP(p-LRPtr,q),r);q-LRPtr=XorP(XorP(q-LRPtr,p),r);r-LRPtr=XorP(p,q); /修改指针return OK;/Insert_XorLinkedList 102.36 Status Delete_XorLinkedList(XorlinkedList pre=NULL;if(i=1) /删除最左结点的情况q=p-LRPtr;
18、q-LRPtr=XorP(q-LRPtr,p);L.left=q;free(p);return OK;j=1;q=p-LRPtr;while(+jLRPtr,pre);pre=p;p=q;/while /找到待删结点 qif(!q) return INFEASIBLE; /i 不可以超过表长if(L.right=q) /q 为最右结点的情况p-LRPtr=XorP(p-LRPtr,q);L.right=p;free(q);return OK;r=XorP(q-LRPtr,p); /q 为中间结点的情况,此时 p,r 分别为其左右结点p-LRPtr=XorP(XorP(p-LRPtr,q),r)
19、;r-LRPtr=XorP(XorP(r-LRPtr,q),p); /修改指针free(q);return OK;/Delete_XorLinkedList 2.37 void OEReform(DuLinkedList while(p-next!=Lp=p-next; /此时 p 指向最后一个奇数结点if(p-next=L) p-next=L-pre-pre;else p-next=l-pre;p=p-next; /此时 p 指向最后一个偶数结点while(p-pre-pre!=L)p-next=p-pre-pre;p=p-next;p-next=L; /按题目要求调整了 next 链的结构,此时 pre 链仍为原状for(p=L;p-next!=L;p=p-next) p-next-pre=p;L-pre=p; /调整 pre 链的结构,同 2.32 方法/OEReform分析:next 链和 pre 链的调整只能分开进行.如同时进行调整的话,必须使用堆栈保存偶数结点的指针,否则将会破坏链表结构,造成结点丢失. 2.38