唐策善数据结构答案-用C语言描述原版.doc_第1页
唐策善数据结构答案-用C语言描述原版.doc_第2页
唐策善数据结构答案-用C语言描述原版.doc_第3页
唐策善数据结构答案-用C语言描述原版.doc_第4页
唐策善数据结构答案-用C语言描述原版.doc_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第二章 线性表(参考答案)2.1 头指针:指向链表的指针。因为对链表的所有操均需从头指针开始,即头指针具有标识链表的作用,所以链表的名字往往用头指针来标识。如:链表的头指针是la,往往简称为“链表la”。头结点:为了链表操作统一,在链表第一元素结点(称为首元结点,或首结点)之前增加的一个结点,该结点称为头结点,其数据域不无实际意义(当然,也可以存储链表长度,这只是副产品),其指针域指向头结点。这样在插入和删除中头结点不变。开始结点:即上面所讲第一个元素的结点。2.2 只设尾指针的单循环链表,从尾指针出发能访问链表上的任何结点。23 设线性表存放在向量A的前elenum个分量中,且递增有序。协议算法将X插入适当位置、void insert(ElemType A,int elenum,ElemType x)/ 向量A目前有elenum个元素,且递增有序,本算法将x插入到向量A中,并保持向量的递增有序。 int i=0,j; while (ielenum & Ai=i;j-) Aj+1=Aj;/ 向后移动元素 Ai=x; / 插入元素 / 算法结束24 void rightrotate(ElemType A,int n,k)/ 以向量作存储结构,本算法将向量中的n个元素循环右移k位,且只用一个辅助空间。 int num=0; / 计数,最终应等于n int start=0; / 记录开始位置(下标) while (numn) temp=Astart; /暂存起点元素值,temp与向量中元素类型相同 empty=start; /保存空位置下标 next=(start-K+n) %n; / 计算下一右移元素的下标 while (next !=start) Aempty=Anext;/ 右移 num+; / 右移元素数加1 empty=next; next=(next-K+n) %n; / 计算新右移元素的下标 Aempty=temp; / 把一轮右移中最后一个元素放到合适位置num+;start+; / 起点增1,若numnext, *pre=L,*s;/ p为工作指针,指向当前元素,pre为前驱指针,指向当前元素的前驱 s=(linklist *)malloc(sizeof(linklist);/申请空间,不判断溢出s-data=x;while (p & p-datanext; / 查找插入位置 pre-next=s; s-next=p; / 插入元素 / 算法结束 26void invert(linklist *L)/ 本算法将带头结点的单链表L逆置。 /算法思想是先将头结点从表上摘下,然后从第一个元素结点开始,依次前插入以L为头结点的链表中。 linklist *p=L-next,*s;/ p为工作指针,指向当前元素,s为p的后继指针 L-next=null;/头结点摘下,指针域置空。算法中头指针L始终不变 while (p)s=p-next; / 保留后继结点的指针 p-next=L-next; / 逆置 L-next=p; p=s; / 将p指向下个待逆置结点 / 算法结束 27(1) int length1(linklist *L)/ 本算法计算带头结点的单链表L的长度 linklist *p=L-next; int i=0;/ p为工作指针,指向当前元素,i 表示链表的长度 while (p) i+; p=p-next; return(i); / 算法结束(2) int length1(node saMAXSIZE)/ 本算法计算静态链表s中元素的个数。 int p=sa0.next, i=0;/ p为工作指针,指向当前元素,i 表示元素的个数,静态链指针等于-1时链表结束while (p!=-1) i+; p=sap.next; return(i); / 算法结束 28void union_invert(linklist *A,*B,*C)/ A和B是两个带头结点的递增有序的单链表,本算法将两表合并成 / 一个带头结点的递减有序单链表C,利用原表空间。 linklist *pa=A-next,*pb=B-next,*C=A,*r;/ pa,pb为工作指针,分别指向A表和B表的当前元素,r为当前逆置/元素的后继指针, 使逆置元素的表避免断开。 /算法思想是边合并边逆置,使递增有序的单链表合并为递减有序的单链表。 C-next=null;/头结点摘下,指针域置空。算法中头指针C始终不变 while (pa & pb) / 两表均不空时作 if (pa-datadata) / 将A表中元素合并且逆置 r=pa-next; / 保留后继结点的指针 pa-next=C-next; / 逆置 C-next=pa; pa=r; / 恢复待逆置结点的指针 else / 将B表中元素合并且逆置 r=pb-next; / 保留后继结点的指针 pb-next=C-next; / 逆置 C-next=pb; pb=r; / 恢复待逆置结点的指针 / 以下while (pa)和while (pb)语句,只执行一个 while (pa) / 将A表中剩余元素逆置 r=pa-next; / 保留后继结点的指针 pa-next=C-next; / 逆置 C-next=pa; pa=r; / 恢复待逆置结点的指针 while (pb) / 将B表中剩余元素逆置 r=pb-next; / 保留后继结点的指针 pb-next=C-next; / 逆置 C-next=pb; pb=r; / 恢复待逆置结点的指针 free(B);/释放B表头结点 / 算法结束 29 void deleteprior(linklist *L)/ 长度大于1的单循环链表,既无头结点,也无头指针,本算法删除*s 的前驱结点 linklist *p=s-next,*pre=s; / p为工作指针,指向当前元素,/ pre为前驱指针,指向当前元素*p的前驱 while (p-next!=s) pre=p; p=p-next; / 查找*s的前驱 pre-next=s;free(p); / 删除元素 / 算法结束 210void one_to_three(linklist *A,*B,*C)/ A是带头结点的的单链表,其数据元素是字符字母、字符、数字字符、其他字符。本算法/将A表分成 / 三个带头结点的循环单链表A、B和C,分别含有字母、数字和其它符号的同一类字符,利用原表空间。 linklist *p=A-next,r;/ p为工作指针,指向A表的当前元素,r为当前元素的后继指针,使表避免断开。 /算法思想是取出当前元素,根据是字母、数字或其它符号,分别插入相应表中。 B=(linklist *)malloc(sizeof(linklist);/申请空间,不判断溢出B-next=null; / 准备循环链表的头结点 C=(linklist *)malloc(sizeof(linklist);/申请空间,不判断溢出C-next=null; / 准备循环链表的头结点 while(p) r=p-next; / 用以记住后继结点 if (p-data=a&p-datadata=A& p-data next=A-next; A-next=p; / 将字母字符插入A表 else if (p-data=0&p-datanext=B-next; B-next=p; / 将数字字符插入B 表 else p-next=C-next; C-next=p;/ 将其它符号插入C 表 p=r; / 恢复后继结点的指针 /while / 算法结束 211void locate(dlinklist *L)/ L是带头结点的按访问频度递减的双向链表,本算法先查找数据x,/ 查找成功时结点的访问频度域增1,最后将该结点按频度递减插入链表中适当位置。 linklist *p=L-next,*q;/p为工作指针,指向L表的当前元素,q为p的前驱,用于查找插入位置。while (p & p-data !=x) p=p-next; / 查找值为x的结点。 if (!p) return (“不存在值为x的结点”);else p-freq+; / 令元素值为x的结点的freq域加1 。p-next-prir=p-prior; / 将p结点从链表上摘下。 p-prior-next=p-next;q=p-prior; / 以下查找p结点的插入位置 while (q !=L & q-freqprior;p-next=q-next; q-next-prior=p;/ 将p结点插入 p-prior=q; q-next=p; / 算法结束 第三章 栈和队列(参考答案)3.3 void sympthy(linklist *head, stack *s)/判断长为n的字符串是否中心对称 int i=1; linklist *p=head-next;while (idata); p=p-next; if (n % 2 !=0) p=p-next;/ 奇数个结点时跳过中心结点 while (p & p-data=pop(s) p=p-next;if (p=null) printf(“链表中心对称”);else printf(“链表不是中心对称”); / 算法结束 3.4int match()/从键盘读入算术表达式,本算法判断圆括号是否正确配对(init s;/初始化栈sscanf(“%c”,&ch);while (ch!=#) /#是表达式输入结束符号switch (ch) case (: push(s,ch); break;case ): if (empty(s) printf(“括号不配对”); exit(0);pop(s);if (!empty(s) printf(“括号不配对”); else printf(“括号配对”); / 算法结束 3.5typedef struct / 两栈共享一向量空间 ElemType vm; / 栈可用空间0m-1 int top2 / 栈顶指针twostack;int push(twostack *s,int i, ElemType x)/ 两栈共享向量空间,i是0或1,表示两个栈,x是进栈元素,/ 本算法是入栈操作 if (abs(s-top0 - s-top1)=1) return(0);/ 栈满 else switch (i)case 0: s-v+(s-top)=x; break;case 1: s-v-(s-top)=x; break;default: printf(“栈编号输入错误”); return(0);return(1); / 入栈成功 / 算法结束 ElemType pop(twostack *s,int i)/ 两栈共享向量空间,i是0或1,表示两个栈,本算法是退栈操作 ElemType x;if (i!=0 & i!=1) return(0);/ 栈编号错误 else switch (i)case 0: if(s-top0=-1) return(0);/栈空else x=s-vs-top-;break;case 1: if(s-top1=m) return(0);/栈空else x=s-vs-top+; break;default: printf(“栈编号输入错误”);return(0);return(x); / 退栈成功 / 算法结束 ElemType top (twostack *s,int i)/ 两栈共享向量空间,i是0或1,表示两个栈,本算法是取栈顶元素操作 ElemType x;switch (i)case 0: if(s-top0=-1) return(0);/栈空else x=s-vs-top; break;case 1: if(s-top1=m) return(0);/栈空else x=s-vs-top; break;default: printf(“栈编号输入错误”);return(0);return(x); / 取栈顶元素成功 / 算法结束 36void Ackerman(int m,int n)/ Ackerman 函数的递归算法 if (m=0) return(n+1);else if (m!=0 & n=0) return(Ackerman(m-1,1);else return(Ackerman(m-1,Ackerman(m,n-1) / 算法结束 37(1) linklist *init(linklist *q)/ q是以带头结点的循环链表表示的队列的尾指针,本算法将队列置空 q=(linklist *)malloc(sizeof(linklist);/申请空间,不判断空间溢出q-next=q;return (q); / 算法结束 (2) linklist *enqueue(linklist *q,ElemType x)/ q是以带头结点的循环链表表示的队列的尾指针,本算法将元素x入队 s=(linklist *)malloc(sizeof(linklist);/申请空间,不判断空间溢出s-next=q-next; / 将元素结点s入队列 q-next=s;q=s; / 修改队尾指针 return (q); / 算法结束 (3) linklist *delqueue(linklist *q)/q是以带头结点的循环链表表示的队列的尾指针,这是出队算法 if (q=q-next) return (null); / 判断队列是否为空 else linklist *s=q-next-next; / s指向出队元素 if (s=q) q=q-next; / 若队列中只一个元素,置空队列else q-next-next=s-next;/ 修改队头元素指针 free (s); / 释放出队结点 return (q); / 算法结束。算法并未返回出队元素 3.8 typedef structElemType datam;/ 循环队列占m个存储单元 int front,rear; / front和rear为队头元素和队尾元素的指针 / 约定front指向队头元素的前一位置,rear指向队尾元素 sequeue; int queuelength(sequeue *cq)/ cq为循环队列,本算法计算其长度 return (cq-rear - cq-front + m) % m; / 算法结束 3.9 typedef structElemType sequm;/ 循环队列占m个存储单元 int rear,quelen; / rear指向队尾元素,quelen为元素个数sequeue;(1) int empty(sequeue *cq)/ cq为循环队列,本算法判断队列是否为空 return (cq-quelen=0 ? 1: 0); / 算法结束 (2) sequeue *enqueue(sequeue *cq,ElemType x)/ cq是如上定义的循环队列,本算法将元素x入队if (cq-quelen=m) return(0); / 队满 else cq-rear=(cq-rear+1) % m; / 计算插入元素位置 cq-sequcq-rear=x; / 将元素x入队列 cq-quelen+; / 修改队列长度 return (cq); / 算法结束 ElemType delqueue(sequeue *cq)/ cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素 if (cq-quelen=0) return(0); / 队空 else int front=(cq-rear - cq-quelen + 1+m) % m;/ 出队元素位置 cq-quelen-; / 修改队列长度 return (cq-sequfront); / 返回队头元素 / 算法结束第四章 串 (参考答案)4.2 用串的去其他运算构成子串的定位运算index。 int index(string s,t)/s,t是字符串,本算法求子串t在主串s中的第一次出现,若s串中包含t串,返回其/第一个字符在s中的位置,否则返回0m=length(s); n=length(t);i=1;while(i=m-n+1)if(strcmp(substr(s,i,n),t)=0) break;else i+;if(inext; q=Y-next; pre=p;while (p & q) ch=p-data; / 取X中的字符 while (q & q-data!=ch) q=q-next; / 和Y中字符比较 if (!q) return(ch); / 找到Y中没有的字符 else pre=p-next; / 上一字符在Y中存在,p=pre; / 取X中下一字符。 q=Y-next; / 再从Y的第一个字符开始比较return(null); / X中字符在Y中均存在 / 算法结束 4.6 是设计一算法,在顺序串上实现串的比较运算 strcmp(s,t)int strcmp(seqstring *S, seqstring *T)/ S和T是指向两个顺序串的指针,本算法比较两个串的大小,若S串大于T串,返回1;若S串等于T串,返回0;否则返回-1 int i=0;while (s-chi!=0 & t-chi!=0)if (s-chit-chi) return(1);else if (s-chichi) return(-1);else i+; / 比较下一字符 if (s-chi!=0& t-chi=0) return(1);else if (s-chi=0& t-chi!=0) return(-1);else return(0);/ 算法结束4.7 linkstring *invert(linkstring *S, linkstring *T)/ S和T是用带头结点的结点大小为1的单链表表示的串,S是主串,T是/ 模式串。本算法是先模式匹配,查找T在S中的第一次出现。如模式匹/ 配成功,则将S中的子串(T串)逆置。linkstring *pre,*sp, *tp; pre=S; / pre是前驱指针,指向S中与T匹配时,T 中的前驱 sp=S-next; tp=T-next;/sp 和tp分别是S和T串上的工作指针 while (sp & tp)if (sp-data=tp-data) / 相等时后移指针 sp=sp-next; tp=tp-next;else / 失配时主串回溯到下一个字符,子串再以第一个字符开始pre=pre-next; sp=pre-next; tp=T-next;if (tp!=null) return (null); / 匹配失败,没有逆置 else / 以下是T串逆置 tp=pre-next; / tp是逆置的工作指针,现在指向待逆置的第一个字符pre-next=sp; / 将S中与T串匹配时的前驱指向匹配后的后继 while (tp!=sp) r=tp-next;tp-next=pre-next;pre-next=tp;tp=r/ 算法结束 第五章 多维数组和广义表(参考答案)5.1 A2323A0000 , A0001 , A0002 A0010 , A0011 , A0012 A0100 , A0101 , A0102 A0110 , A0111 , A0112 A0200 , A0201 , A0202 A0210 , A0211 , A0212 将第一维的0变为1后,可列出另外18个元素。以行序为主(即行优先)时,先改变右边的下标,从右到左进行。5.2 设各维上下号为c1d1,c2d2,c3d3,每个元素占l个单元。LOC(aijk)=LOC(ac1c2c3)+(i-c1)*(d2-c2+1)*(d3-c3+1)+(j-c2)*(d3-c3+1)+(k-c3)*l推广到n维数组!(下界和上界)为(ci,di),其中1=i=n.则:其数据元素的存储位置为:LOC(aj1j2.jn)=LOC(ac1c2cn)+(d2-c2+1) (dn-cn+1)(j1-c1)+(d3-c3+1) (dn-cn+1)n(j2-c2)+(dn-cn+1)(jn-1-cn-1)+(jn-cn)*l=LOC(ac1c2c3)+ i(ji-ci) i=1n其中i(dk-ck+1)(1=ilchild);br=height(bt-rchild);return(blbr? bl+1: br+1); / 左右子树高度的大者加1(根) / 算法结束 6.227,19,2,6,32,3,21,10其对应字母分别为a,b,c,e,f,g,h。哈夫曼编码:a:0010b:10c:00000d:0001e:01f:00001g:11h:0011第七章 图(参考答案)71(1)邻接矩阵中非零元素的个数的一半为无向图的边数;(2)Aij= =0为顶点,I 和j无边,否则j和j有边相通;(3)任一顶点I的度是第I行非0元素的个数。73(1)邻接表(2)从顶点4开始的DFS序列:V5,V3,V4,V6,V2,V1(3)从顶点4开始的BFS序列:V4,V5,V3,V6,V1,V276简单回路指起点和终点相同的简单路径。算法基本思想是利用图的遍历,以顶点VK开始,若遍历中再通到VK,则存在简单回路,否则不存在简单回路。Adjlisttp g ; visited1.n=0;Int found =0;/全程变量Int dfs(btxptr x)/从k顶点深度优先遍历图g,看是否存在k的简单回路 visitedx=1;p=gx.firstarc;while(p!=null) w=p-adjvex;if(w= =k) found=1;exit(0);/有简单回路,退出if (!visitedk ) dfs(w );p=p-nextarc;/while(p!=null)/ dfs711void toposort_dfs (graph g;vtptr v)/从顶点v开始,利用深度优先遍历对图g进行拓扑排序。/基本思想是利用栈s存放顶点,首先出栈的顶点是出度为0的顶点,是拓扑序列中最后一个顶/点。若出栈元素个数等于顶点数,则拓扑排序成功,输出的是逆拓扑排序序列。 visited1.n=0;top=0;num=0;/初始化;top为栈顶指针,num记出栈元素数s+top=v;/顶点入栈while (top!=0) w=firstadj(g,v);/求顶点v的第一邻接点while (w!=0) / w!=0的含义是w存在 if ( !visitedw) s+top=w;w=nextadj(g,v,w);/求下一个邻接点if (top!=0) v=stop-; num+; printf(v);/输出顶点printf(“n”);if (num=i+1;j-) / 向前起泡,一趟有一最小冒出 if (rjrj-1; exchange=1; / 有交换 for (j= i+1;j=n-I;j+) / 向后起泡,一趟有一最大沉底 if (rjrj+1) rjrj+1; exchange=1; / 有交换 i+; / end of WHILE exchange /算法结束 8.6void QuickSort(rectype rn+1; int n)/ 对r1.n进行快速排序的非递归算法 typedef struct int low,high; nodenode sn+1;int top;int quickpass(rectype r,int,int); / 函数声明 top=1; stop.low=1; stop.high=n;while (top0)ss=stop.low; tt=stop.high; top-;if (ss1) top+; stop.low=ss; stop.high=k-1;if (tt-k1) top+; stop.low=k+1; stop.high=tt; / 算法结束 int quickpass(rectype r;int s,t)i=s; j=t; rp=ri; x=ri.key;while (ij)while (ij & x=rj.key) j-;if (ij) ri+=rj; while (i=rj.key) i+;if (i0)k=quickpass(r,ss,tt);if (k-sstt-k) / 一趟排序后分割成左右两部分 if (k-ss1) / 左部子序列长度大于右部,左部进栈 top+; stop.low=ss; stop.high=k-1; if (tt-k1) ss=k+1; / 右部短的直接处理 else flag=false; / 右部处理完,需退栈 else if (tt-k1) /右部子序列长度大于左部,右部进栈 top=top+1; stop.low=k+1; stop.high=tt; if (k-ss1) tt=k-1 / 左部短的直接处理 else flag=false / 左部处理完,需退栈 if (!flag & top0)ss=stop.low; tt=stop.high; top-; flag=true; / end of while (flag | top0) / 算法结束 int quickpass(rectype r;int s,t)/ 用“三者取中法”对8.6进行改进 int i=s, j=t, mid=(s+t)/2; rectype tmp;if (ri.keyrmid.key) tmp=ri;ri=rmid;rmid=tmp if (rmid.keyrj.key)tmp=rj;rj=rmid;if (tmpri) rmid=tmp; else rmid=ri;ri=tmp tmp=ri;ri=rmid;rmid=tmp / 三者取中:最佳2次比较3次移动;最差3次比较10次移动 rp=ri; x=ri.key;while (ij)while (ij & x=rj.key) j-;if (ij) ri+=rj; while (i=rj.key) i+;if (ij) rj-=ri;ri=rp; return (i); / 一次划分算法结束 8.8viod searchjrec(rectype r,int j)/在无序记录rn中,找到第j(0=jn)个记录。算法利用快速排序思想,找到第一/轴元素的位置i,若i=j则查找结束。否则根据ji在0i、1或i+1n+1之间查/找,直到/i=j为止。 int quichpass (rectype r,int,int) / 函数声明i=quichpass(r,0,n-1); / 查找枢轴位置whilehile(i!=j)if (ji) i=quichpass(r,0.i-1);else i=quichpass(r,i+1.n-1);/ searchjrec算法结束8.9viod rearrange (rectype r,int n)/本算法重排具有n个元素的数r,使取负值的关键字放到取非负值的关键字之前。 int i=0,j=n-1; rp=r0;while(ij)while(i=0) j-;if(ij) ri+=rj;/取负值关键字记录放到左面while(ij&ri.key0) i+;if(ij) rj-=ri/ 取非负值关键字记录放到右面/while(ij)8.9void arrange(rectype rn+1; int n)/ 对r1.n进行整理,使关键字为负值的记录排在非负值的记录之前 int i=0, j=-1;rp=r0; while (ij) while (i=0) j-;if (ij) ri+=rj; /将关键字取负值的记录放到前面while (ij & ri.key0) i+;if (inext;while (p-next!=null) / 剩最后一个元素时,排序结束 q=p; / 设当前结点为最小 s=p-next; / s指向待比较结点 while (s!=null)if (s-dataq-data) s=s-next;else q=s; s=s-next; / 用指向新的最小 if (q!=p) x=q-data; q-data=p-data; p-data=x; p=p-next; / 链表指针后移,指向下一个最小值结点 /算法结束 8.14 void CountSort(rectype r; int n);/ 对r0.n-1进行计数排序 int cn = 0;/ c数组初始化,元素值指其在r中的位置。如ci=j,(0=i,jn)/ 则意味着ri 应在r的第 j 位置上。for (i=0;in;i+) / 一趟扫描比较选出大小,给数组 c 赋值for (j=i+1;jrj) ci=ci+1else cj=cj+1;for (i=0;ik) i-;if (i0 & ri.key=k) return(i); else return(0) / 算法结束 查找过程的判定树是单支树。查找成功的平均查找长度为ASL=PICI =1/n*i = 1/2*(n+1)查找不成功的平均查找长度为 ASL=1/(n+1)(i+(n+1)=(n+2)/2.9

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论