《数据结构用C语言描述》习题答案.docx

上传人:b****3 文档编号:10816055 上传时间:2023-05-27 格式:DOCX 页数:83 大小:100.85KB
下载 相关 举报
《数据结构用C语言描述》习题答案.docx_第1页
第1页 / 共83页
《数据结构用C语言描述》习题答案.docx_第2页
第2页 / 共83页
《数据结构用C语言描述》习题答案.docx_第3页
第3页 / 共83页
《数据结构用C语言描述》习题答案.docx_第4页
第4页 / 共83页
《数据结构用C语言描述》习题答案.docx_第5页
第5页 / 共83页
《数据结构用C语言描述》习题答案.docx_第6页
第6页 / 共83页
《数据结构用C语言描述》习题答案.docx_第7页
第7页 / 共83页
《数据结构用C语言描述》习题答案.docx_第8页
第8页 / 共83页
《数据结构用C语言描述》习题答案.docx_第9页
第9页 / 共83页
《数据结构用C语言描述》习题答案.docx_第10页
第10页 / 共83页
《数据结构用C语言描述》习题答案.docx_第11页
第11页 / 共83页
《数据结构用C语言描述》习题答案.docx_第12页
第12页 / 共83页
《数据结构用C语言描述》习题答案.docx_第13页
第13页 / 共83页
《数据结构用C语言描述》习题答案.docx_第14页
第14页 / 共83页
《数据结构用C语言描述》习题答案.docx_第15页
第15页 / 共83页
《数据结构用C语言描述》习题答案.docx_第16页
第16页 / 共83页
《数据结构用C语言描述》习题答案.docx_第17页
第17页 / 共83页
《数据结构用C语言描述》习题答案.docx_第18页
第18页 / 共83页
《数据结构用C语言描述》习题答案.docx_第19页
第19页 / 共83页
《数据结构用C语言描述》习题答案.docx_第20页
第20页 / 共83页
亲,该文档总共83页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

《数据结构用C语言描述》习题答案.docx

《《数据结构用C语言描述》习题答案.docx》由会员分享,可在线阅读,更多相关《《数据结构用C语言描述》习题答案.docx(83页珍藏版)》请在冰点文库上搜索。

《数据结构用C语言描述》习题答案.docx

《数据结构用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(n)

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->freqprior;

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证明:

由jpk说明pj在pk之后出栈,即pj被pk压在下面,后进先出。

由以上两条,不可能存在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

{char

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工作范文 > 行政公文

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2