数据结构C语言版第三四章习题答案Word文档格式.docx

上传人:b****5 文档编号:17418127 上传时间:2022-12-01 格式:DOCX 页数:21 大小:43.83KB
下载 相关 举报
数据结构C语言版第三四章习题答案Word文档格式.docx_第1页
第1页 / 共21页
数据结构C语言版第三四章习题答案Word文档格式.docx_第2页
第2页 / 共21页
数据结构C语言版第三四章习题答案Word文档格式.docx_第3页
第3页 / 共21页
数据结构C语言版第三四章习题答案Word文档格式.docx_第4页
第4页 / 共21页
数据结构C语言版第三四章习题答案Word文档格式.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

数据结构C语言版第三四章习题答案Word文档格式.docx

《数据结构C语言版第三四章习题答案Word文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构C语言版第三四章习题答案Word文档格式.docx(21页珍藏版)》请在冰豆网上搜索。

数据结构C语言版第三四章习题答案Word文档格式.docx

A.top不变B.top=0C.top--D.top++

(10)设计一个判别表达式中左,右括号是否配对出现的算法,采用( )数据结构最佳。

A.线性表的顺序存储结构B.队列

C.线性表的链式存储结构D.栈

(11)用链接方式存储的队列,在进行删除运算时( )。

A.仅修改头指针B.仅修改尾指针

C.头、尾指针都要修改D.头、尾指针可能都要修改

(12)循环队列存储在数组A[0..m]中,则入队时的操作为( )。

A.rear=rear+1B.rear=(rear+1)%(m-1)

C.rear=(rear+1)%mD.rear=(rear+1)%(m+1)

(13)最大容量为n的循环队列,队尾指针是rear,队头是front,则队空的条件是( )。

A.(rear+1)%n==frontB.rear==front

C.rear+1==frontD.(rear-l)%n==front

(14)栈和队列的共同点是( )。

A.都是先进先出B.都是先进后出

C.只允许在端点处插入和删除元素D.没有共同点

(15)一个递归算法必须包括( )。

A.递归部分B.终止条件和递归部分

C.迭代部分D.终止条件和迭代部分

(2)回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。

试写一个算法判定给定的字符向量是否为回文。

(提示:

将一半字符入栈) 

根据提示,算法可设计为:

 //以下为顺序栈的存储结构定义

 #defineStackSize100//假定预分配的栈空间最多为100个元素

 typedefcharDataType;

//假定栈元素的数据类型为字符

 typedefstruct{

  DataTypedata[StackSize];

  inttop;

 }SeqStack;

 intIsHuiwen(char*t)

  {//判断t字符向量是否为回文,若是,返回1,否则返回0

   SeqStacks;

   inti,len;

   chartemp;

   InitStack(&

s);

   len=strlen(t);

//求向量长度

   for(i=0;

i<

len/2;

i++)//将一半字符入栈

    Push(&

s,t[i]);

   while(!

EmptyStack(&

s))

    {//每弹出一个字符与相应字符比较

     temp=Pop(&

     if(temp!

=S[i]) 

return0;

//不等则返回0

     elsei++;

    } 

   return1;

//比较完毕均相等则返回1

  }

(3)设从键盘输入一整数的序列:

a1,a2,a3,…,an,试编写算法实现:

用栈结构存储输入的整数,当ai≠-1时,将ai进栈;

当ai=-1时,输出栈顶整数并出栈。

算法应对异常情况(入栈满等)给出相应的信息。

#definemaxsize栈空间容量

voidInOutS(ints[maxsize])

//s是元素为整数的栈,本算法进行入栈和退栈操作。

{inttop=0;

//top为栈顶指针,定义top=0时为栈空。

for(i=1;

=n;

i++)//n个整数序列作处理。

{scanf(“%d”,&

x);

//从键盘读入整数序列。

if(x!

=-1)//读入的整数不等于-1时入栈。

if(top==maxsize-1){printf(“栈满\n”);

exit(0);

}elses[++top]=x;

//x入栈。

else//读入的整数等于-1时退栈。

{if(top==0){printf(“栈空\n”);

}elseprintf(“出栈元素是%d\n”,s[top--]);

}}

}//算法结束。

(4)从键盘上输入一个后缀表达式,试编写算法计算表达式的值。

规定:

逆波兰表达式的长度不超过一行,以$符作为输入结束,操作数之间用空格分隔,操作符只可能有+、-、*、/四种运算。

例如:

23434+2*$。

[题目分析]逆波兰表达式(即后缀表达式)求值规则如下:

设立运算数栈OPND,对表达式从左到右扫描(读入),当表达式中扫描到数时,压入OPND栈。

当扫描到运算符时,从OPND退出两个数,进行相应运算,结果再压入OPND栈。

这个过程一直进行到读出表达式结束符$,这时OPND栈中只有一个数,就是结果。

floatexpr()

//从键盘输入逆波兰表达式,以‘$’表示输入结束,本算法求逆波兰式表达式的值。

{floatOPND[30];

//OPND是操作数栈。

 init(OPND);

//两栈初始化。

floatnum=0.0;

//数字初始化。

scanf(“%c”,&

//x是字符型变量。

while(x!

=’$’)

{switch

{case‘0’<

=x<

=’9’:

while((x>

=’0’&

&

x<

=’9’)||x==’.’)//拼数

=’.’)//处理整数

{num=num*10+(ord(x)-ord(‘0’));

scanf(“%c”,&

}

else//处理小数部分。

{scale=10.0;

while(x>

=’9’)

{num=num+(ord(x)-ord(‘0’)/scale;

scale=scale*10;

}//else

push(OPND,num);

num=0.0;

//数压入栈,下个数初始化

casex=‘’:

break;

//遇空格,继续读下一个字符。

casex=‘+’:

push(OPND,pop(OPND)+pop(OPND));

casex=‘-’:

x1=pop(OPND);

x2=pop(OPND);

push(OPND,x2-x1);

casex=‘*’:

push(OPND,pop(OPND)*pop(OPND));

casex=‘/’:

push(OPND,x2/x1);

default:

//其它符号不作处理。

}//结束switch

//读入表达式中下一个字符。

}//结束while(x!

=‘$’)

printf(“后缀表达式的值为%f”,pop(OPND));

}//算法结束。

[算法讨论]假设输入的后缀表达式是正确的,未作错误检查。

算法中拼数部分是核心。

若遇到大于等于‘0’且小于等于‘9’的字符,认为是数。

这种字符的序号减去字符‘0’的序号得出数。

对于整数,每读入一个数字字符,前面得到的部分数要乘上10再加新读入的数得到新的部分数。

当读到小数点,认为数的整数部分已完,要接着处理小数部分。

小数部分的数要除以10(或10的幂数)变成十分位,百分位,千分位数等等,与前面部分数相加。

在拼数过程中,若遇非数字字符,表示数已拼完,将数压入栈中,并且将变量num恢复为0,准备下一个数。

这时对新读入的字符进入‘+’、‘-’、‘*’、‘/’及空格的判断,因此在结束处理数字字符的case后,不能加入break语句。

(5)假设以I和O分别表示入栈和出栈操作。

栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序列。

下面所示的序列中哪些是合法的?

A.IOIIOIOOB.IOOIOIIOC.IIIOIOIOD.IIIOOIOO

通过对

的分析,写出一个算法,判定所给的操作序列是否合法。

若合法,返回true,否则返回false(假定被判定的操作序列已存入一维数组中)。

A和D是合法序列,B和C是非法序列。

设被判定的操作序列已存入一维数组A中。

intJudge(charA[])

//判断字符数组A中的输入输出序列是否是合法序列。

如是,返回true,否则返回false。

{i=0;

//i为下标。

j=k=0;

//j和k分别为I和字母O的的个数。

while(A[i]!

=‘\0’)//当未到字符数组尾就作。

{switch(A[i])

{case‘I’:

j++;

break;

//入栈次数增1。

case‘O’:

k++;

if(k>

j){printf(“序列非法\n”);

i++;

//不论A[i]是‘I’或‘O’,指针i均后移。

if(j!

=k){printf(“序列非法\n”);

return(false);

else{printf(“序列合法\n”);

return(true);

[算法讨论]在入栈出栈序列(即由‘I’和‘O’组成的字符串)的任一位置,入栈次数(‘I’的个数)都必须大于等于出栈次数(即‘O’的个数),否则视作非法序列,立即给出信息,退出算法。

整个序列(即读到字符数组中字符串的结束标记‘\0’),入栈次数必须等于出栈次数(题目中要求栈的初态和终态都为空),否则视为非法序列。

(6)假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素站点(注意不设头指针),试编写相应的置空队、判队空、入队和出队等算法。

算法如下:

 //先定义链队结构:

 typedefstructqueuenode{

   Datatypedata;

   structqueuenode*next;

  }QueueNode;

//以上是结点类型的定义

   queuenode*rear;

  }LinkQueue;

//只设一个指向队尾元素的指针

 

(1)置空队

  voidInitQueue(LinkQueue*Q)

   {//置空队:

就是使头结点成为队尾元素

    QueueNode*s;

    Q->

rear=Q->

rear->

next;

//将队尾指针指向头结点

    while(Q->

rear!

=Q->

next)//当队列非空,将队中元素逐个出队

     {s=Q->

      Q->

next=s->

      free(s);

     }//回收结点空间

   }

 

(2)判队空 

  intEmptyQueue(LinkQueue*Q)

   {//判队空

    //当头结点的next指针指向自己时为空队

    returnQ->

next->

next==Q->

 (3)入队

  voidEnQueue(LinkQueue*Q,Datatypex)

   {//入队

    //也就是在尾结点处插入元素

    QueueNode*p=(QueueNode*)malloc(sizeof(QueueNode));

//申请新结点

    p->

data=x;

p->

next=Q->

//初始化新结点并链入

    Q-rear->

next=p;

rear=p;

//将尾指针移至新结点

 (4)出队

  DatatypeDeQueue(LinkQueue*Q)

   {//出队,把头结点之后的元素摘下

    Datatypet;

    QueueNode*p;

    if(EmptyQueue(Q))

      Error("

Queueunderflow"

);

    p=Q->

//p指向将要摘下的结点

    x=p->

//保存结点中数据

    if(p==Q->

rear)

     {//当队列中只有一个结点时,p结点出队后,要将队尾指针指向头结点

Q->

next=p->

    else 

//摘下结点p

    free(p);

//释放被删结点

    returnx;

(7)假设以数组Q[m]存放循环队列中的元素,同时设置一个标志tag,以tag==0和tag==1来区别在队头指针(front)和队尾指针(rear)相等时,队列状态为“空”还是“满”。

试编写与此结构相应的插入(enqueue)和删除(dlqueue)算法。

【解答】

循环队列类定义

#include<

assert.h>

template<

classType>

classQueue{//循环队列的类定义

public:

Queue(int=10);

~Queue(){delete[]Q;

voidEnQueue(Type&

item);

TypeDeQueue();

TypeGetFront();

voidMakeEmpty(){front=rear=tag=0;

}//置空队列

intIsEmpty()const{returnfront==rear&

tag==0;

}//判队列空否

intIsFull()const{returnfront==rear&

tag==1;

}//判队列满否

private:

intrear,front,tag;

//队尾指针、队头指针和队满标志

Type*Q;

//存放队列元素的数组

intm;

//队列最大可容纳元素个数

}

构造函数

Queue<

Type>

:

Queue(intsz):

rear(0),front(0),tag(0),m(sz){

//建立一个最大具有m个元素的空队列。

Q=newType[m];

//创建队列空间

assert(Q!

=0);

//断言:

动态存储分配成功与否

插入函数

template<

voidQueue<

:

EnQueue(Type&

item){

assert(!

IsFull());

//判队列是否不满,满则出错处理

rear=(rear+1)%m;

//队尾位置进1,队尾指针指示实际队尾位置

Q[rear]=item;

//进队列

tag=1;

//标志改1,表示队列不空

删除函数

TypeQueue<

DeQueue(){

IsEmpty());

//判断队列是否不空,空则出错处理

front=(front+1)%m;

//队头位置进1,队头指针指示实际队头的前一位置

tag=0;

//标志改0,表示栈不满

returnQ[front];

//返回原队头元素的值

读取队头元素函数

GetFront(){

returnQ[(front+1)%m];

//返回队头元素的值

(8)如果允许在循环队列的两端都可以进行插入和删除操作。

要求:

写出循环队列的类型定义;

写出“从队尾删除”和“从队头插入”的算法。

[题目分析]用一维数组v[0..M-1]实现循环队列,其中M是队列长度。

设队头指针front和队尾指针rear,约定front指向队头元素的前一位置,rear指向队尾元素。

定义front=rear时为队空,(rear+1)%m=front为队满。

约定队头端入队向下标小的方向发展,队尾端入队向下标大的方向发展。

(1)#defineM队列可能达到的最大长度

typedefstruct

{elemtpdata[M];

intfront,rear;

}cycqueue;

(2)elemtpdelqueue(cycqueueQ)

//Q是如上定义的循环队列,本算法实现从队尾删除,若删除成功,返回被删除元素,否则给出出错信息。

{if(Q.front==Q.rear){printf(“队列空”);

exit(0);

Q.rear=(Q.rear-1+M)%M;

//修改队尾指针。

return(Q.data[(Q.rear+1+M)%M]);

//返回出队元素。

}//从队尾删除算法结束

voidenqueue(cycqueueQ,elemtpx)

//Q是顺序存储的循环队列,本算法实现“从队头插入”元素x。

{if(Q.rear==(Q.front-1+M)%M){printf(“队满”;

Q.data[Q.front]=x;

//x入队列

Q.front=(Q.front-1+M)%M;

//修改队头指针。

}//结束从队头插入算法。

(9)已知Ackermann函数定义如下:

写出计算Ack(m,n)的递归算法,并根据此算法给出出Ack(2,1)的计算过程。

写出计算Ack(m,n)的非递归算法。

intAck(intm,n)

{if(m==0)return(n+1);

elseif(m!

=0&

n==0)return(Ack(m-1,1));

elsereturn(Ack(m-1,Ack(m,m-1));

}//算法结束

(1)Ack(2,1)的计算过程

Ack(2,1)=Ack(1,Ack(2,0))//因m<

>

0,n<

0而得

=Ack(1,Ack(1,1))//因m<

0,n=0而得

=Ack(1,Ack(0,Ack(1,0)))//因m<

=Ack(1,Ack(0,Ack(0,1)))//因m<

=Ack(1,Ack(0,2))//因m=0而得

=Ack(1,3)//因m=0而得

=Ack(0,Ack(1,2))//因m<

=Ack(0,Ack(0,Ack(1,1)))//因m<

=Ack(0,Ack(0,Ack(0,Ack(1,0))))//因m<

=Ack(0,Ack(0,Ack(0,Ack(0,1))))//因m<

=Ack(0,Ack(0,Ack(0,2)))//因m=0而得

=Ack(0,Ack(0,3))//因m=0而得

=Ack(0,4)//因n=0而得

=5//因n=0而得

(2)intAckerman(intm,intn)

{intakm[M][N];

inti,j;

for(j=0;

j<

N;

j++)akm[0][j];

=j+1;

i<

m;

i++)

{akm[i][0]=akm[i-1][1];

for(j=1;

j++)

akm[i][j]=akm[i-1][akm[i][j-1]];

return(akm[m][n]);

(10)已知f为单链表的表头指针,链表中存储的都是整型数据,试写出实现下列运算的递归算法:

求链表中的最大整数;

求链表的结点个数;

求所有整数的平均值。

#include<

iostream.h>

//定义在头文件"

RecurveList.h"

classList;

classListNode{//链表结点类

friendclassList;

private:

intdata;

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

当前位置:首页 > 高中教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1