唐策善数据结构答案用c语言描述原版.docx
- 文档编号:25788155
- 上传时间:2023-06-14
- 格式:DOCX
- 页数:30
- 大小:35.01KB
唐策善数据结构答案用c语言描述原版.docx
《唐策善数据结构答案用c语言描述原版.docx》由会员分享,可在线阅读,更多相关《唐策善数据结构答案用c语言描述原版.docx(30页珍藏版)》请在冰豆网上搜索。
唐策善数据结构答案用c语言描述原版
第二章线性表(参考答案)
2.1头指针:
指向链表的指针。
因为对链表的所有操均需从头指针开始,即头指针具有标识链表的作用,所以链表的名字往往用头指针来标识。
如:
链表的头指针是la,往往简称为“链表la”。
头结点:
为了链表操作统一,在链表第一元素结点(称为首元结点,或首结点)之前增加的一个结点,该结点称为头结点,其数据域不无实际意义(当然,也可以存储链表长度,这只是副产品),其指针域指向头结点。
这样在插入和删除中头结点不变。
开始结点:
即上面所讲第一个元素的结点。
2.2只设尾指针的单循环链表,从尾指针出发能访问链表上的任何结点。
2·3设线性表存放在向量A[]的前elenum个分量中,且递增有序。
协议算法将X插入适当位置、
voidinsert(ElemTypeA[],intelenum,ElemTypex)
//向量A目前有elenum个元素,且递增有序,本算法将x插入到向量A中,并保持向量的递增有序。
{inti=0,j;
while(i for(j=elenum-1;j>=i;j--)A[j+1]=A[j];//向后移动元素 A[i]=x;//插入元素 }//算法结束 2·4 voidrightrotate(ElemTypeA[],intn,k) //以向量作存储结构,本算法将向量中的n个元素循环右移k位,且只用一个辅助空间。 {intnum=0;//计数,最终应等于n intstart=0;//记录开始位置(下标) while(num {temp=A[start];//暂存起点元素值,temp与向量中元素类型相同 empty=start;//保存空位置下标 next=(start-K+n)%n;//计算下一右移元素的下标 while(next! =start) {A[empty]=A[next];//右移 num++;//右移元素数加1 empty=next; next=(next-K+n)%n;//计算新右移元素的下标 } A[empty]=temp;//把一轮右移中最后一个元素放到合适位置 num++; start++;//起点增1,若num } }//算法结束 2·5 voidinsert(linklist*L,ElemTypex) //带头结点的单链表L递增有序,本算法将x插入到链表中,并保持链表的递增有序。 {linklist*p=L->next,*pre=L,*s; //p为工作指针,指向当前元素,pre为前驱指针,指向当前元素的前驱 s=(linklist*)malloc(sizeof(linklist));//申请空间,不判断溢出 s->data=x; while(p&&p->data<=x){pre=p;p=p->next;}//查找插入位置 pre->next=s;s->next=p;//插入元素 }//算法结束 2·6 voidinvert(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指向下个待逆置结点 } }//算法结束 2·7 (1)intlength1(linklist*L) //本算法计算带头结点的单链表L的长度 {linklist*p=L->next;inti=0; //p为工作指针,指向当前元素,i表示链表的长度 while(p) {i++;p=p->next;} return(i); }//算法结束 (2)intlength1(nodesa[MAXSIZE]) //本算法计算静态链表s中元素的个数。 {intp=sa[0].next,i=0; //p为工作指针,指向当前元素,i表示元素的个数,静态链指针等于-1时链表结束 while(p! =-1) {i++;p=sa[p].next;} return(i); }//算法结束 2·8 voidunion_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->data<=pb->data)//将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表头结点 }//算法结束 2·9 voiddeleteprior(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);//删除元素 }//算法结束 2·10 voidone_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->data<=’z’||p->data>=’A’&&p->data<=’Z’) {p->next=A->next;A->next=p;}//将字母字符插入A表 elseif(p->data>=’0’&&p->data<=’9’) {p->next=B->next;B->next=p;}//将数字字符插入B表 else{p->next=C->next;C->next=p;}//将其它符号插入C表 p=r;//恢复后继结点的指针 }//while }//算法结束 2·11 voidlocate(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->freq p->next=q->next;q->next->prior=p;//将p结点插入 p->prior=q;q->next=p; } }//算法结束 第三章栈和队列(参考答案) 3.3voidsympthy(linklist*head,stack*s) //判断长为n的字符串是否中心对称 {inti=1;linklist*p=head->next; while(i<=n/2)//前一半字符进栈 {push(s,p->data);p=p->next;} if(n%2! ==0)p=p->next;//奇数个结点时跳过中心结点 while(p&&p->data==pop(s))p=p->next; if(p==null)printf(“链表中心对称”); elseprintf(“链表不是中心对称”); }//算法结束 3.4 intmatch() //从键盘读入算术表达式,本算法判断圆括号是否正确配对 (inits;//初始化栈s scanf(“%c”,&ch); while(ch! =’#’)//’#’是表达式输入结束符号 switch(ch) {case’(’: push(s,ch);break; case’)’: if(empty(s)){printf(“括号不配对”);exit(0);} pop(s); } if(! empty(s))printf(“括号不配对”); elseprintf(“括号配对”); }//算法结束 3.5 typedefstruct//两栈共享一向量空间 {ElemTypev[m];//栈可用空间0—m-1 inttop[2]//栈顶指针 }twostack; intpush(twostack*s,inti,ElemTypex) //两栈共享向量空间,i是0或1,表示两个栈,x是进栈元素, //本算法是入栈操作 {if(abs(s->top[0]-s->top[1])==1)return(0);//栈满 else{switch(i) {case0: s->v[++(s->top)]=x;break; case1: s->v[--(s->top)]=x;break; default: printf(“栈编号输入错误”);return(0); } return (1);//入栈成功 } }//算法结束 ElemTypepop(twostack*s,inti) //两栈共享向量空间,i是0或1,表示两个栈,本算法是退栈操作 {ElemTypex; if(i! =0&&i! =1)return(0);//栈编号错误 else{switch(i) {case0: if(s->top[0]==-1)return(0);//栈空 elsex=s->v[s->top--];break; case1: if(s->top[1]==m)return(0);//栈空 elsex=s->v[s->top++];break; default: printf(“栈编号输入错误”);return(0); } return(x);//退栈成功 } }//算法结束 ElemTypetop(twostack*s,inti) //两栈共享向量空间,i是0或1,表示两个栈,本算法是取栈顶元素操作 {ElemTypex; switch(i) {case0: if(s->top[0]==-1)return(0);//栈空 elsex=s->v[s->top];break; case1: if(s->top[1]==m)return(0);//栈空 elsex=s->v[s->top];break; default: printf(“栈编号输入错误”);return(0); } return(x);//取栈顶元素成功 }//算法结束 3.6 voidAckerman(intm,intn) //Ackerman函数的递归算法 {if(m==0)return(n+1); elseif(m! =0&&n==0)return(Ackerman(m-1,1); elsereturn(Ackerman(m-1,Ackerman(m,n-1)) }//算法结束 3.7 (1)linklist*init(linklist*q) //q是以带头结点的循环链表表示的队列的尾指针,本算法将队列置空 {q=(linklist*)malloc(sizeof(linklist));//申请空间,不判断空间溢出 q->next=q; return(q); }//算法结束 (2)linklist*enqueue(linklist*q,ElemTypex) //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;//若队列中只一个元素,置空队列 elseq->next->next=s->next;//修改队头元素指针 free(s);//释放出队结点 } return(q); }//算法结束。 算法并未返回出队元素 3.8 typedefstruct {ElemTypedata[m];//循环队列占m个存储单元 intfront,rear;//front和rear为队头元素和队尾元素的指针 //约定front指向队头元素的前一位置,rear指向队尾元素 }sequeue; intqueuelength(sequeue*cq) //cq为循环队列,本算法计算其长度 {return(cq->rear-cq->front+m)%m; }//算法结束 3.9 typedefstruct {ElemTypesequ[m];//循环队列占m个存储单元 intrear,quelen;//rear指向队尾元素,quelen为元素个数 }sequeue; (1)intempty(sequeue*cq) //cq为循环队列,本算法判断队列是否为空 {return(cq->quelen==0? 1: 0); }//算法结束 (2)sequeue*enqueue(sequeue*cq,ElemTypex) //cq是如上定义的循环队列,本算法将元素x入队 {if(cq->quelen==m)return(0);//队满 else{cq->rear=(cq->rear+1)%m;//计算插入元素位置 cq->sequ[cq->rear]=x;//将元素x入队列 cq->quelen++;//修改队列长度 } return(cq); }//算法结束 ElemTypedelqueue(sequeue*cq) //cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素 {if(cq->quelen==0)return(0);//队空 else{intfront=(cq->rear-cq->quelen+1+m)%m;//出队元素位置 cq->quelen--;//修改队列长度 return(cq->sequ[front]);//返回队头元素 } }//算法结束 第四章串(参考答案) 4.2用串的去其他运算构成子串的定位运算index。 intindex(strings,t) //s,t是字符串,本算法求子串t在主串s中的第一次出现,若s串中包含t串,返回其 //第一个字符在s中的位置,否则返回0 {m=length(s);n=length(t); i=1; while(i<=m-n+1) if(strcmp(substr(s,i,n),t)==0)break; elsei++; if(i<=m-n+1)return(i);//模式匹配成功 elsereturn(0);//s串中无子串t }//算法index结束 4.4将S=“(xyz)*”转为T=“(x+z)*y” S=concat(S,substr(S,3,1))//”(xyz)*y” S=replace(S,3,1,”+”)//”(x+z)*y” 4.5 charsearch(linkstring*X,linkstring*Y) //X和Y是用带头结点的结点大小为1的单链表表示的串,本算法查找X中第一个不在Y中出现的字符。 算法思想是先从X中取出一个字符,到Y中去查找,如找到,则在X中取下一字符,重复以上过程;若没找到,则该字符为所求 {linkstring*p,*q,*pre;//p,q为工作指针,pre控制循环 p=X->next;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) intstrcmp(seqstring*S,seqstring*T) //S和T是指向两个顺序串的指针,本算法比较两个串的大小,若S串大于T串,返回1;若S串等于T串,返回0;否则返回-1 {inti=0; while(s->ch[i]! =’\0’&&t->ch[i]! =’\0’) if(s->ch[i]>t->ch[i])return (1); elseif(s->ch[i] elsei++;//比较下一字符 if(s->ch[i]! =’\0’&&t->ch[i]==0)return (1); elseif(s->ch[i]==’\0’&&t->ch[i]! =0)return(-1); elsereturn(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)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 唐策善 数据结构 答案 语言 描述 原版