第三章 栈和队列
一、选择题
1.B |
2.1B |
2.2A |
2.3B |
2.4D |
2.5.C |
3.B |
4.D |
5.D |
6.C |
7.D |
8.B |
9.D |
10.D |
11.D |
12.C |
13.B |
14.C |
15.B |
16.D |
17.B |
18.B |
19.B |
20.D |
21.D |
22.D |
23.D |
24.C |
25.A |
26.A |
27.D |
28.B |
29.BD |
30.C |
31.B |
32.C |
33.1B |
33.2A |
33.3C |
33.4C |
33.5F |
34.C |
35.C |
36.A |
37.AD |
|
|
|
二、判断题
1.√ |
2.√ |
3. √ |
4. √ |
5.× |
6.√ |
7.√ |
8. √ |
9. √ |
10.× |
11. √ |
12.× |
13. × |
14.× |
15. √ |
16.× |
17.√ |
18.× |
19.√ |
20. √ |
|
|
|
|
部分答案解释如下。
1、 尾递归的消除就不需用栈
2、 这个数是前序序列为1,2,3,…,n,所能得到的不相似的二叉树的数目。
三 、填空题
1、操作受限(或限定仅在表尾进行插入和删除操作) 后进先出
2、栈 3、3 1 2 4、23 100CH 5、0 n+1 top[1]+1=top[2]
6、两栈顶指针值相减的绝对值为1(或两栈顶指针相邻)。
7、(1)满 (2)空 (3)n (4)栈底 (5)两栈顶指针相邻(即值之差的绝对值为1)
8、链式存储结构 9、S×SS×S×× 10、data[++top]=x;
11、23.12.3*2-4/34.5*7/++108.9/+(注:表达式中的点(.)表示将数隔开,如23.12.3是三个数)
12、假溢出时大量移动数据元素。
13、(M+1) MOD N (M+1)% N; 14、队列 15、先进先出 16、先进先出
17、s=(LinkedList)malloc(sizeof(LNode)); s->data=x;s->next=r->next;r->next=s;r=s;
18、牺牲一个存储单元 设标记
19、(TAIL+1)MOD M=FRONT (数组下标0到M-1,若一定使用1到M,则取模为0者,值改取M
20、sq.front=(sq.front+1)%(M+1);return(sq.data(sq.front));(sq.rear+1)%(M+1)==sq.front;
21、栈 22、(rear-front+m)% m; 23、(R-P+N)% N;
24、(1)a[i]或a[1] (2)a[i] (3)pop(s)或s[1];
25、(1)PUSH(OPTR,w)(2)POP(OPTR)(3)PUSH(OPND,operate(a,theta,b))
26、(1)T>0(2)i<n(3)T>0(4)top<n(5)top+1(6)true(7)i-1(8)top-1(9)T+w[i](10)false
四 、应用题
1、栈是只准在一端进行插入和删除操作的线性表,允许插入和删除的一端叫栈顶,另一端叫栈底。最后插入的元素最先删除,故栈也称后进先出(LIFO)表。
2、队列是允许在一端插入而在另一端删除的线性表,允许插入的一端叫队尾,允许删除的一端叫队头。最先插入队的元素最先离开(删除),故队列也常称先进先出(FIFO)表。
3、 用常规意义下顺序存储结构的一维数组表示队列,由于队列的性质(队尾插入和队头删除),容易造成“假溢出”现象,即队尾已到达一维数组的高下标,不能再插 入,然而队中元素个数小于队列的长度(容量)。循环队列是解决“假溢出”的一种方法。通常把一维数组看成首尾相接。在循环队列下,通常采用“牺牲一个存储 单元”或“作标记”的方法解决“队满”和“队空”的判定问题。
4、(1)通常有两条规则。第一是给定序列中S的个数和X的个数相等;第二是从给定序列的开始,到给定序列中的任一位置,S的个数要大于或等于X的个数。
(2)可以得到相同的输出元素序列。例如,输入元素为A,B,C,则两个输入的合法序列ABC和BAC均可得到输出元素序列ABC。对于合法序列ABC,我们使用本题约定的S×S×S×操作序列;对于合法序列BAC,我们使用SS××S×操作序列。
5、三个:CDEBA,CDBEA,CDBAE
6、输入序列为123456,不能得出435612,其理由是,输出序列最后两元素是12,前面4个元素(4356)得到后,栈中元素剩12,且2在栈顶,不可能栈底元素1在栈顶元素2之前出栈。
得到135426的过程如下:1入栈并出栈,得到部分输出序列1;然后2和3入栈,3出栈,部分输出序列变为:13;接着4和5入栈,5,4和2依次出栈,部分输出序列变为13542;最后6入栈并退栈,得最终结果135426。
7、能得到出栈序列B、C、A、E、D,不能得到出栈序列D、B、A、C、E。其理由为:若出栈序列以D开头,说明在D之前的入栈元素是A、B和C,三个元素中C是栈顶元素,B和A不可能早于C出栈,故不可能得到D、B、A、C、E出栈序列。
8、借助栈结构,n个入栈元素可得到1/(n+1)((2n)!/(n!*n!))种出栈序列。本题4个元素,可有14种出栈序列,abcd和dcba就是其中两种。但dabc和adbc是不可能得到的两种。
9、不能得到序列2,5,3,4,6。栈可以用单链表实现,这就是链栈。由于栈只在栈顶操作,所以链栈通常不设头结点。
10、如果i<j,则对于pi<pj情况,说明pi在pj入栈前先出栈。而对于pi>pj的情况,则说明要将pj压到pi之上,也就是在pj出栈之后pi才能出栈。这就说明,对于i<j<k,不可能出现pj<pk<pi的输出序列。换句话说,对于输入序列1,2,3,不可能出现3,1,2的输出序列。
11、(1)能得到325641。在123依次进栈后,3和2出栈,得部分输出序列32;然后4,5入栈,5出栈,得部分出栈序列325;6入栈并出栈,得部分输出序列3256;最后退栈,直到栈空。得输出序列325641。其操作序列为AAADDAADADDD。
(2)不能得到输出顺序为154623的序列。部分合法操作序列为ADAAAADDAD,得到部分输出序列1546后,栈中元素为23,3在栈顶,故不可能2先出栈,得不到输出序列154623。
12、(1)一个函数在结束本函数之前,直接或间接调用函数自身,称为递归。例如,函数f在执行中,又调用函数f自身,这称为直接递归;若函数f在执行中,调用函数g,而g在执行中,又调用函数f,这称为间接递归。在实际应用中,多为直接递归,也常简称为递归。
(2)递归程序的优点是程序结构简单、清晰,易证明其正确性。缺点是执行中占内存空间较多,运行效率低。
(3)递归程序执行中需借助栈这种数据结构来实现。
(4)递归程序的入口语句和出口语句一般用条件判断语句来实现。递归程序由基本项和归纳项组成。基本项是递归程序出口,即不再递归即可求出结果的部分;归纳项是将原来问题化成简单的且与原来形式一样的问题,即向着“基本项”发展,最终“到达”基本项。
13、函数调用结束时vol=14。执行过程图示如下:
vol(4) vol(4)=vol(3)+5
14 =vol(2)+3+5
=vol(1)+4+3+5
vol(3)+5 =vol(0)+2+4+3+5
9 =0+2+4+3+5
=14
vol(2)+3
6
vol(1)+4
2
vol(0)+2
0
14、过程p递归调用自身时,过程p由内部定义的局部变量在p的2次调用期间,不占同一数据区。每次调用都保留其数据区,这是递归定义所决定,用“递归工作栈”来实现。
15、设Hn为n个盘子的Hanoi塔的移动次数。(假定n个盘子从钢针X移到钢针Z,可借助钢针Y)
则 Hn =2Hn-1+1 //先将n-1个盘子从X移到Y,第n个盘子移到Z,再将那n-1个移到Z
=2(2Hn-2+1)+1
=22 Hn-2+2+1
=22(2Hn-3+1)+2+1
=23 Hn-3+22+2+1
·
·
·
= 2k Hn-k+2k-1 +2k-2 +…+21 +20
=2n-1 H1+2n-2+2n-3+…+21+20
因为H1=1,所以原式Hn=2n-1+2n-2+…+21+20=2n-1
故总盘数为n的Hanoi塔的移动次数是2n-1。
16、运行结果为:1 2 1 3 1 2 1(注:运行结果是每行一个数,为节省篇幅,放到一行。)
17、两栈共享一向量空间(一维数组),栈底设在数组的两端,两栈顶相邻时为栈满。设共享数组为S[MAX],则一个栈顶指针为-1,另一个栈顶指针为MAX时,栈为空。
用C写的入栈操作push(i,x)如下:
const MAX=