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

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

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

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

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

第三章栈和队列习题数据结构推荐文档

习题三栈和队列

一单项选择题

1.在作进栈运算时,应先判别栈是否(①),在作退栈运算时应先判别栈是否(②)。

当栈中元素为n个,作进栈运算时发生上溢,则说明该栈的最大容量为(③)。

①,②:

A.空B.满C.上溢D.下溢

③:

A.n-1B.nC.n+1D.n/2

2.若已知一个栈的进栈序列是1,2,3,…,n,其输出序列为p1,p2,p3,...,pn,若p1=3,则p2为()。

A可能是2B一定是2C可能是1D一定是1

3.有六个元素6,5,4,3,2,1的顺序进栈,问下列哪一个不是合法的出栈序列?

()

A.543612B.453126C.346521D.234156

4.设有一顺序栈S,元素s,s,s,s,s,s依次进栈,如果6个元素出栈的顺序是s,s,s,s,6244513236s,s,则栈的容量至少应该是()15A.2B.3C.5D.6

5.若栈采用顺序存储方式存储,现两栈共享空间V[1..m],top[i]代表第i个栈(i=1,2)栈顶,栈1的底在v[1],栈2的底在V[m],则栈满的条件是()。

A.|top[2]-top[1]|=0B.top[1]+1=top[2]

C.top[1]+top[2]=mD.top[1]=top[2]

6.执行完下列语句段后,i值为:

()

intf(intx)

{return((x>0)?

x*f(x-1):

2);}

inti;

i=f(f

(1));

A.2B.4C.8D.无限递归

7.表达式3*2^(4+2*2-6*3)-5求值过程中当扫描到6时,对象栈和算符栈为(),其中^为乘幂。

A.3,2,4,1,1;(*^(+*-B.3,2,8;(*^-

C.3,2,4,2,2;(*^(-D.3,2,8;(*^(-

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

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

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

9.递归过程或函数调用时,处理参数及返回地址,要用一种称为()的数据结构。

A.队列B.多维数组C.栈D.线性表

10.设C语言数组Data[m+1]作为循环队列SQ的存储空间,front为队头指针,rear为队尾指针,则执行出队操作的语句为()

A.front=front+1B.front=(front+1)%m

C.rear=(rear+1)%(m+1)D.front=(front+1)%(m+1)

11.循环队列的队满条件为()

A.(sq.rear+1)%maxsize==(sq.front+1)%maxsize;

B.(sq.front+1)%maxsize==sq.rear

C.(sq.rear+1)%maxsize==sq.front

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;

p->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:

stack):

Boolean;判栈空否

队列的ADT函数有:

enqueue(q:

queue:

value:

datatype);元素value进队

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

queue):

datatype;

判队列空否isEmpty(q:

queue):

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×S××

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满:

如果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);

#-

x=POP(OPND);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->next;}

p=head;

while(notemptystack(s))

{pop(s,p->data);p=p->next;}

}

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:

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

}

}//算法结束。

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

只检查圆括号的配对。

一般情况是检查花括号(‘{',‘}')、方括号(‘[',‘]')和圆括号(‘(',‘)')的配对问题。

编写算法中如遇左括号(‘{',‘[',或‘(')就压入栈中,如遇右括号(‘}',‘]',或‘)'),则与栈顶元素比较,如是与其配对的括号(左花括号,左方括号或左圆括号),则弹出栈顶元素;否则,就结论括号不配对。

在读入表达式结束符‘#'时,栈中若应只剩‘#',表示括号全部配对成功;否则表示括号不匹配。

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

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

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++;break;//入栈次数增1。

exit(0);}

;)”\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(“栈号输入不对”);exit(0);}

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

switch(i)

{case0:

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

(1);break;

case1:

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

(1);

}

}//push

(2)退栈操作

elemtppop(inti)

//退栈算法。

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

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

{if(i<0||i>1){printf(“栈号输入错误\n”);exit(0);}

switch(i)

{case0:

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

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

case1:

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(“栈满”);return(0);}//s1满s2非空,这时s1不能再入栈。

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

{while(!

Sempty(s1)){POP(s1,x);PUSH(s2,x);}

PUSH(s1,x);return

(1);//x入栈,实现了队列元素的入队。

}

(2)voiddequeue(stacks2,s1)

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

{if(!

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

{POP(s2,x);printf(“出队元素为”,x);}

else//处理s2空栈。

if(Sempty(s1)){printf(“队列空”);exit(0);}//若输入栈也为空,则判定队空。

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

{while(!

Sempty(s1)){POP(s1,x);PUSH(s2,x);}

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