《数据结构用C语言描述》+课后题答案.docx
- 文档编号:30478775
- 上传时间:2023-08-15
- 格式:DOCX
- 页数:81
- 大小:100.76KB
《数据结构用C语言描述》+课后题答案.docx
《《数据结构用C语言描述》+课后题答案.docx》由会员分享,可在线阅读,更多相关《《数据结构用C语言描述》+课后题答案.docx(81页珍藏版)》请在冰豆网上搜索。
《数据结构用C语言描述》+课后题答案
习题解答(唐策善版)(其他版本在上面)
第一章绪论(参考答案)
1.3
(1)O(n)
(2)
(2) O(n)
(3)(3) O(n)
(4)(4) O(n1/2)
(5)(5) 执行程序段的过程中,x,y值变化如下:
循环次数xy
0(初始)91100
192100
293100
………………
9100100
10101100
119199
1292100
………………
2010199
219198
………………
3010198
319197
到y=0时,要执行10*100次,可记为O(10*y)=O
(1)
1.52100,(2/3)n,log2n,n1/2,n3/2,(3/2)n,nlog2n,2n,n!
nn
第二章线性表(参考答案)
在以下习题解答中,假定使用如下类型定义:
(1)顺序存储结构:
#defineMAXSIZE1024
typedefintElemType;//实际上,ElemType可以是任意类型
typedefstruct
{ElemTypedata[MAXSIZE];
intlast;//last表示终端结点在向量中的位置
}sequenlist;
(2)链式存储结构(单链表)
typedefstructnode
{ElemTypedata;
structnode*next;
}linklist;
(3)链式存储结构(双链表)
typedefstructnode
{ElemTypedata;
structnode*prior,*next;
}dlinklist;
(4)静态链表
typedefstruct
{ElemTypedata;
intnext;
}node;
nodesa[MAXSIZE];
2.1头指针:
指向链表的指针。
因为对链表的所有操均需从头指针开始,即头指针具有标识链表的作用,所以链表的名字往往用头指针来标识。
如:
链表的头指针是la,往往简称为“链表la”。
头结点:
为了链表操作统一,在链表第一元素结点(称为首元结点,或首结点)之前增加的一个结点,该结点称为头结点,其数据域不无实际意义(当然,也可以存储链表长度,这只是副产品),其指针域指向头结点。
这样在插入和删除中头结点不变。
开始结点:
即上面所讲第一个元素的结点。
2.2只设尾指针的单循环链表,从尾指针出发能访问链表上的任何结点。
2·3
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 } }//算法结束 算法二 算法思想: 先将左面n-k个元素逆置,接着将右面k个元素逆置,最后再将这n个元素逆置。 voidrightrotate(ElemTypeA[],intn,k) //以向量作存储结构,本算法将向量中的n个元素循环右移k位,且只用一个辅助空间。 {ElemTypetemp; for(i=0;i<(n-k)/2;i++)//左面n-k个元素逆置 {temp=A[i];A[i]=A[n-k-1-i];A[n-k-1-i]=temp;} for(i=1;i<=k;i++)//右面k个元素逆置 {temp=A[n-k-i];A[n-k-i]=A[n-i];A[n-i]=temp;} for(i=0;i {temp=A[i];A[i]=A[n-1-i];A[n-1-i]=temp;} }//算法结束 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.11234213432144321 124321433241 132423143421 13422341 14322431 设入栈序列元素数为n,则可能的出栈序列数为C2nn=(1/n+1)*(2n! /(n! )2) 3.2证明: 由j 由以上两条,不可能存在i 也就是说,若有1,2,3顺序入栈,不可能有3,1,2的出栈序列。 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]);//返回队头元素 } }//算法结束 第四章串(参考答案) 在以下习题解答中,假定使用如下类型定义: #defineMAXSIZE1024 typedefstruct {ch
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构用C语言描述 数据结构 语言 描述 课后 答案
![提示](https://static.bdocx.com/images/bang_tan.gif)