第三章栈和队列习题 数据结构推荐文档Word下载.docx

上传人:b****5 文档编号:19512239 上传时间:2023-01-07 格式:DOCX 页数:14 大小:24.28KB
下载 相关 举报
第三章栈和队列习题 数据结构推荐文档Word下载.docx_第1页
第1页 / 共14页
第三章栈和队列习题 数据结构推荐文档Word下载.docx_第2页
第2页 / 共14页
第三章栈和队列习题 数据结构推荐文档Word下载.docx_第3页
第3页 / 共14页
第三章栈和队列习题 数据结构推荐文档Word下载.docx_第4页
第4页 / 共14页
第三章栈和队列习题 数据结构推荐文档Word下载.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

第三章栈和队列习题 数据结构推荐文档Word下载.docx

《第三章栈和队列习题 数据结构推荐文档Word下载.docx》由会员分享,可在线阅读,更多相关《第三章栈和队列习题 数据结构推荐文档Word下载.docx(14页珍藏版)》请在冰豆网上搜索。

第三章栈和队列习题 数据结构推荐文档Word下载.docx

D.sq.rear==sq.front

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

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

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

二、填空题

1.栈是_______的线性表,其运算遵循_______的原则。

2.一个栈的输入序列是:

1,2,3则不可能的栈输出序列是_______。

3.用S表示入栈操作,X表示出栈操作,若元素入栈的顺序为1234,为了得到1342出栈顺序,相应的S和X的操作串为_______。

4.循环队列的引入,目的是为了克服_______。

5.队列是限制插入只能在表的一端,而删除在表的另一端进行的线性表,其特点是_______。

6.已知链队列的头尾指针分别是f和r,则将值x入队的操作序列是_______。

7.表达式求值是_______应用的一个典型例子。

8.循环队列用数组A[0..m-1]存放其元素值,已知其头尾指针分别是front和rear,则当前队列的元素个数是_______。

9.以下运算实现在链栈上的初始化,请在________________处用请适当句子予以填充。

VoidInitStacl(LstackTp*ls){________________;

10.`以下运算实现在链栈上的进栈,请在处用请适当句子予以填充。

VoidPush(LStackTp*ls,DataTypex)

{LstackTp*p;

p=malloc(sizeof(LstackTp));

________________;

p->

next=ls;

}

11.以下运算实现在链栈上的退栈,请在________________处用请适当句子予以填充。

IntPop(LstackTp*ls,DataType*x)

{LstackTp*p;

if(ls!

=NULL)

{p=ls;

*x=________________;

ls=ls->

next;

return

(1);

}elsereturn(0);

12.以下运算实现在链队上的入队列,请在________________处用适当句子予以填充。

VoidEnQueue(QueptrTp*lq,DataTypex)

{LqueueTp*p;

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

________________=x;

next=NULL;

(lq->

rear)->

next=________________;

三、应用题

1.给出栈的两种存储结构形式名称,在这两种栈的存储结构中如何判别栈空与栈满?

2.画出对算术表达式A-B*C/D-E↑F求值时操作数栈和运算符栈的变化过程。

3.将两个栈存入数组V[1..m]应如何安排最好?

这时栈空、栈满的条件是什么?

4.怎样判定循环队列的空和满?

四、算法设计题

1.借助栈(可用栈的基本运算)来实现单链表的逆置运算。

2.设表达式以字符形式已存入数组E[n]中,‘#'

为表达式的结束符,试写出判断表达式中括号(‘('

和‘)'

)是否配对的C语言描述算法:

EXYX(E);

(注:

算法中可调用栈操作的基本算法。

3.假设以I和O分别表示入栈和出栈操作。

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

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

A.IOIIOIOOB.IOOIOIIOC.IIIOIOIOD.IIIOOIOO

(2)通过对

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

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

4.设有两个栈S,S都采用顺序栈方式,并且共享一个存储区[O..maxsize-1],为了尽量利21用空间,减少溢出的可能,可采用栈顶相向,迎面增长的存储方式。

试设计S,S有关入栈21和出栈的操作算法。

5.请利用两个栈S1和S2来模拟一个队列。

已知栈的三个运算定义如下:

PUSH(ST,x):

元素x入ST栈;

POP(ST,x):

ST栈顶元素出栈,赋给变量x;

Sempty(ST):

判ST栈是否为空。

那么如何利用栈的运算来实现该队列的三个运算:

enqueue:

插入一个元素入队列;

dequeue:

删除一个元素出队列;

queue_empty:

判队列为空。

(请写明算法的思想及必要的注释)

6.要求循环队列不损失一个空间全部都能得到利用,设置一个标志tag,以tag为0或1来区分头尾指针相同时的队列状态的空与满,请编写与此相应的入队与出队算法。

7.已知Q是一个非空队列,S是一个空栈。

仅用队列和栈的ADT函数和少量工作变量,编写一个算法,将队列Q中的所有元素逆置。

栈的ADT函数有:

makeEmpty(s:

stack);

置空栈

push(s:

stack;

value:

datatype);

新元素value进栈

pop(s:

stack):

datatype;

出栈,返回栈顶值

isEmpty(s:

Boolean;

判栈空否

队列的ADT函数有:

enqueue(q:

queue:

元素value进队

出队列,返回队头值deQueue(q:

queue):

判队列空否isEmpty(q:

boolean;

第3章栈和队列

1.BAB

2.A

3.C

4.B

5.B

6.B

7.D

8.D

9.C

10.D

11.C

12.C

1.操作受限(或限定仅在表尾进行插入和删除操作)后进先出

2.312

3.S×

SS×

×

4.假溢出时大量移动数据元素

5.先进先出

6.s=(LinkedList)malloc(sizeof(LNode));

s->

data=x;

s->

next=r->

next;

r->

next=s;

r=s;

7.栈

8.(rear-front+m)%m;

9.ls=NULL

10.p->

data=x,ls=p

11.p->

data,free(p)

12.p->

data,p,lq->

rear=p

1.【解答】

(1)顺序栈(top用来存放栈顶元素的下标)

判断栈S空:

如果S->

top==-1表示栈空。

判断栈S满:

top==Stack_Size-1表示栈满。

(2)链栈(top为栈顶指针,指向当前栈顶元素前面的头结点)

判断栈空:

如果top->

next==NULL表示栈空。

判断栈满:

当系统没有可用空间时,申请不到空间存放要进栈的元素,此时栈满。

2.设操作数栈是opnd,操作符栈是optr,对算术表达式A-B*C/D-E↑F求值,过程如下:

步骤opnd栈optr栈输入字符主要操作

PUSH(OPTR,'

#'

)初始F#A-B*C/D-E#↑PUSH(OPND,A)#AA-B*C/D-1E↑F#-B*C/D-E↑F#-PUSH(OPTR,'

A2#-'

)PUSH(OPND,B)

E↑F#B*C/D-#-

AB

3

4AB#-**C/DE↑FPUSH(OPTR,'

*'

PUSH(OPND,C)

5ABC

#-*

C/DE↑FPUSH(OPND,POP(OPND)*POP(OPND))6AT(T=B*C)#-//DE↑FPUSH(OPTR,'

/'

ATD

#-/

D7E↑FPUSH(OPND,D)

AT(T=T/D)8

x=POP(OPND);

y=POP(OPND)E↑F#-

T(T=A-T)PUSH(OPND,y/x);

#-

y=POP(OPND);

PUSH(OPND,y-x)

PUSH(OPTR,'

9TE#-PUSH(OPND,E)F#

F#TEPUSH(OPTR,‘↑'

#10

F#

PUSH(OPND,F)

TEF

#11

#X=POP(OPND)Y=POP(OPND)12TE

POP(OPTR)PUSH(OPND,x)TS(S=#-

F)x=POP(OPND)y=POP(OPND)

#POP(OPTR)PUSH(OPND,y-x)

R(R=T-S)

3.设栈S1和栈S2共享向量V[1..m],初始时,栈S1的栈顶指针top[0]=0,栈S2的栈顶指针top[1]=m+1,当top[0]=0为左栈空,top[1]=m+1为右栈空;

当top[0]=0并且top[1]=m+1时为全栈空。

当top[1]-top[0]=1时为栈满。

4.设顺序存储队列用一维数组q[m]表示,其中m为队列中元素个数,队列中元素在向量中的下标从0到m-1。

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

当front等于-1时队空,rear等于m-1时为队满。

由于队列的性质(“删除”在队头而“插入”在队尾),所以当队尾指针rear等于m-1时,若front不等于-1,则队列中仍有空闲单元,所以队列并不是真满。

这时若再有入队操作,会造成假“溢出”。

其解决办法有二,一是将队列元素向前“平移”(占用0至rear-front-1);

二是将队列看成首尾相连,即循环队列(0..m-1)。

在循环队列下,仍定义front=rear时为队空,而判断队满则用两种办法,一是用“牺牲一个单元”,即rear+1=front(准确记是(rear+1)%m=front,m是队列容量)时为队满。

另一种解法是“设标记”方法,如设标记tag,tag等于0情况下,若删除时导致front=rear为队空;

tag=1情况下,若因插入导致front=rear则为队满。

四算法设计题

1.解:

方法是先依次让单链表上的元素进栈,然后再依次出栈。

Voidinvert(lklisthead)

{LstackTps;

initstack(s);

p=head;

while(p<

>

null)

{Push(s,p->

data);

p=p->

p=head;

while(notemptystack(s))

{pop(s,p->

p=p->

2.[题目分析]判断表达式中括号是否匹配,可通过栈,简单说是左括号时进栈,右括号时退栈。

退栈时,若栈顶元素是左括号,则新读入的右括号与栈顶左括号就可消去。

如此下去,输入表达式结束时,栈为空则正确,否则括号不匹配。

intEXYX(charE[],intn)

//E[]是有n字符的字符数组,存放字符串表达式,以‘#'

结束。

本算法判断表达式中圆括号是否匹配。

{chars[30];

//s是一维数组,容量足够大,用作存放括号的栈。

inttop=0;

//top用作栈顶指针。

s[top]=‘#'

;

//‘#'

先入栈,用于和表达式结束符号‘#'

匹配。

inti=0;

//字符数组E的工作指针。

while(E[i]!

=‘#'

)//逐字符处理字符表达式的数组。

switch(E[i])

{case‘('

:

s[++top]=‘('

i++;

break;

case‘)'

if(s[top]==‘('

{top--;

i++;

break;

else{printf(“括号不配对”);

exit(0);

case‘#'

if(s[top]==‘#'

){printf(“括号配对\n”);

return

(1);

else{printf(“括号不配对\n”);

return(0);

}//括号不配对

default:

//读入其它字符,不作处理。

}//算法结束。

[算法讨论]本题是用栈判断括号匹配的特例:

只检查圆括号的配对。

一般情况是检查花括号(‘{'

,‘}'

)、方括号(‘['

,‘]'

)和圆括号(‘('

,‘)'

)的配对问题。

编写算法中如遇左括号(‘{'

,‘['

,或‘('

)就压入栈中,如遇右括号(‘}'

,或‘)'

),则与栈顶元素比较,如是与其配对的括号(左花括号,左方括号或左圆括号),则弹出栈顶元素;

否则,就结论括号不配对。

在读入表达式结束符‘#'

时,栈中若应只剩‘#'

,表示括号全部配对成功;

否则表示括号不匹配。

另外,由于本题只是检查括号是否匹配,故对从表达式中读入的不是括号的那些字符,一律未作处理。

再有,假设栈容量足够大,因此入栈时未判断溢出。

3.

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

(2)设被判定的操作序列已存入一维数组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++;

//入栈次数增1。

)”\n(k>

j){printf(“序列非法if‘O'

k++;

case

i++;

//不论A[i]是‘I'

或‘O'

,指针i均后移。

if(j!

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

return(false);

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

return(true);

[算法讨论]在入栈出栈序列(即由‘I'

和‘O'

组成的字符串)的任一位置,入栈次数(‘I'

的个数)都必须大于等于出栈次数(即‘O'

的个数),否则视作非法序列,立即给出信息,退出算法。

整个序列(即读到字符数组中字符串的结束标记‘\0'

),入栈次数必须等于出栈次数(题目中要求栈的初态和终态都为空),否则视为非法序列。

4.[题目分析]两栈共享向量空间,将两栈栈底设在向量两端,初始时,s1栈顶指针为-1,s2栈顶为maxsize。

两栈顶指针相邻时为栈满。

两栈顶相向,迎面增长,栈顶指针指向栈顶元素。

#definemaxsize两栈共享顺序存储空间所能达到的最多元素数

#defineelemtpint//假设元素类型为整型

typedefstruct

{elemtpstack[maxsize];

//栈空间

inttop[2];

//top为两个栈顶指针

}stk;

stks;

//s是如上定义的结构类型变量,为全局变量。

(1)入栈操作:

intpush(inti,intx)

//入栈操作。

i为栈号,i=0表示左边的栈s1,i=1表示右边的栈s2,x是入栈元素。

入栈成功返回1,否则返回0。

{if(i<

0||i>

1){printf(“栈号输入不对”);

if(s.top[1]-s.top[0]==1){printf(“栈已满\n”);

return(0);

switch(i)

{case0:

s.stack[++s.top[0]]=x;

return

(1);

case1:

s.stack[--s.top[1]]=x;

}//push

(2)退栈操作

elemtppop(inti)

//退栈算法。

i代表栈号,i=0时为s1栈,i=1时为s2栈。

退栈成功返回退栈元素,否则返回-1。

{if(i<

0||i>

1){printf(“栈号输入错误\n”);

switch(i)

if(s.top[0]==-1){printf(“栈空\n”);

return(-1);

elsereturn(s.stack[s.top[0]--]);

if(s.top[1]==maxsize{printf(“栈空\n”);

return(-1);

elsereturn(s.stack[s.top[1]++]);

}//算法结束

请注意算法中两栈入栈和退栈时的栈顶指针的计算。

两栈共享空间示意图]算法讨论[

略,s1栈是通常意义下的栈,而s2栈入栈操作时,其栈顶指针左移(减1),退栈时,栈顶指针右移(加1)。

5.[题目分析]栈的特点是后进先出,队列的特点是先进先出。

所以,用两个栈s1和s2模拟一个队列时,s1作输入栈,逐个元素压栈,以此模拟队列元素的入队。

当需要出队时,将栈s1退栈并逐个压入栈s2中,s1中最先入栈的元素,在s2中处于栈顶。

s2退栈,相当于队列的出队,实现了先进先出。

显然,只有栈s2为空且s1也为空,才算是队列空。

(1)intenqueue(stacks1,elemtpx)

//s1是容量为n的栈,栈中元素类型是elemtp。

本算法将x入栈,若入栈成功返回1,否则返回0。

{if(top1==n&

&

!

Sempty(s2))//top1是栈s1的栈顶指针,是全局变量。

{printf(“栈满”);

}//s1满s2非空,这时s1不能再入栈。

if(top1==n&

Sempty(s2))//若s2为空,先将s1退栈,元素再压栈到s2。

{while(!

Sempty(s1)){POP(s1,x);

PUSH(s2,x);

PUSH(s1,x);

//x入栈,实现了队列元素的入队。

(2)voiddequeue(stacks2,s1)

//s2是输出栈,本算法将s2栈顶元素退栈,实现队列元素的出队。

{if(!

Sempty(s2))//栈s2不空,则直接出队。

{POP(s2,x);

printf(“出队元素为”,x);

else//处理s2空栈。

if(Sempty(s1)){printf(“队列空”);

}//若输入栈也为空,则判定队空。

else//先将栈s1倒入s2中,再作出队操作。

POP(s2,x);

//s2退栈相当队列出队。

printf(“出队元素”,x);

}//结束算法dequue。

(3)intqueue_empty()

//本算法判用栈s1和s2模拟的队列是否为空。

{if(Sempty(s1)&

Sempty(s2))return

(1);

//队列空。

elsereturn(0);

//队列不空。

[算法讨论]算法中假定栈s1和栈s2容量相同。

出队从栈s2出,当s2为空时,若s1不空,则将s1倒入s2再出栈。

入队在s1,当s1满后,若s2空,则将s1倒入s2,之后再入队。

因此队列的容量为两栈容量之和。

元素从栈s1倒入s2,必须在s2空的情况下才能进行,即在要求出队操作时,若s2空,则不论s1元素多少(只要不空),就要全部倒入s2中。

6.【解答】入队算法:

intEnterQueue(SeqQueue*Q,QueueElementTypex

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

当前位置:首页 > 高等教育 > 院校资料

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

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