习题三栈和队列一单项选择题1.在作进栈运算时,应先判别栈是否(①),在作退栈运算时应先判别栈是否(②)。当栈中元素为n个,作进栈运算时发生上溢,则说明该栈的最大容量为(③)。①,②:A.空B.满C.上溢D.下溢③:A.n-1B.nC.n+1D.n/22.若已知一个栈的进栈序列是1,2,3,…,n,其输出序列为p1,p2,p3,...,pn,若p1=3,则p2为()。A可能是2B一定是2C可能是1D一定是13.有六个元素6,5,4,3,2,1的顺序进栈,问下列哪一个不是合法的出栈序列?()A.543612B.453126C.346521D.2341564.设有一顺序栈S,元素s1,s2,s3,s4,s5,s6依次进栈,如果6个元素出栈的顺序是s2,s3,s4,s6,s5,s1,则栈的容量至少应该是()A.2B.3C.5D.65.若栈采用顺序存储方式存储,现两栈共享空间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((x0)?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)%mC.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.rearC.(sq.rear+1)%maxsize==sq.frontD.sq.rear==sq.front12.栈和队列的共同点是()。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.设有两个栈S1,S2都采用顺序栈方式,并且共享一个存储区[O..maxsize-1],为了尽量利用空间,减少溢出的可能,可采用栈顶相向,迎面增长的存储方式。试设计S1,S2有关入栈和出栈的操作算法。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.BAB2.A3.C4.B5.B6.B7.D8.D9.C10.D11.C12.C二、填空题1.操作受限(或限定仅在表尾进行插入和删除操作)后进先出2.3123.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=NULL10.p-data=x,ls=p11.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栈输入字符主要操作初始#A-B*C/D-E↑F#PUSH(OPTR,’#’)1A#A-B*C/D-E↑F#PUSH(OPND,A)2A#--B*C/D-E↑F#PUSH(OPTR,’-’)3AB#-B*C/D-E↑F#PUSH(OPND,B)4AB#-**C/D-E↑F#PUSH(OPTR,’*’)5ABC#-*C/D-E↑F#PUSH(OPND,C)6AT(T=B*C)#-//D-E↑F#PUSH(OPND,POP(OPND)*POP(OPND))PUSH(OPTR,’/’)7ATD#-/D-E↑F#PUSH(OPND,D)8AT(T=T/D)T(T=A-T)#-#--E↑F#x=POP(OPND);y=POP(OPND)PUSH(OPND,y/x);x=POP(OPND);y=POP(OPND);PUSH(OPND,y-x)PUSH(OPTR,’-’)9TE#-E↑F#PUSH(OPND,E)10TE#-↑↑F#PUSH(OPTR,‘↑’)11TEF#-↑F#PUSH(OPND,F)12TETS(S=E↑F)R(R=T-S)#-##X=POP(OPND)Y=POP(OPND)POP(OPTR)PUSH(OPND,y↑x)x=POP(OPND)y=POP(OPND)POP(OPTR)PUSH(OPND,y-x)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则为队满。