第三章 栈和队列习题与解析good.docx
《第三章 栈和队列习题与解析good.docx》由会员分享,可在线阅读,更多相关《第三章 栈和队列习题与解析good.docx(27页珍藏版)》请在冰豆网上搜索。
第三章栈和队列习题与解析good
第四章栈和队列习题
一判断题(y/n)nyynnynnn
1做进栈运算时应先判别,栈是否为空。
2,做退栈运算时应先判别,栈是否为空。
3,当栈中元素为n个,作进栈运算时发生上溢,则说明该栈的最大容量为n.
4,为了增加内存空间的利用率和减少发生上溢的可能性,由两个栈共享一片连续的内存空间时,应将两栈的栈顶分别设在着片内存空间的两端。
5,只有当两个基本栈的栈底在栈空间的某一位置相遇时,才产生上溢。
6,栈是一种线性表,它的特点是后进先出。
7,设一数列的顺序为1,2,3,4,5,6,通过栈结构可以排成的顺序必须是3,2,5,6,4,1.
8,设有一个空栈,栈顶指针为1000H(十六进制,下同),现有输入序列1,2,3,4,5,经过PUSH,PUSH,POP,PUSH,POP,PUSH,PUSH后,输出序列是2,1.
9,设有一个空栈,栈顶指针为1000H(十六进制,下同),现有输入序列1,2,3,4,5,经过PUSH,PUSH,POP,PUSH,POP,PUSH,PUSH后,栈顶指针是不是1005H.
二单选题(请从下列A,B,C,D选项中选择一项)
1,栈的特点是:
先进先出
后进先出
进优于出
出优于进
2,队列的特点是:
先进先出
后进先出
进优于出
出优于进
3,栈与队列都是:
顺序存储的线性结构
链式存储的线性结构
限制存取点的线性结构
限制存取点的非线性结构
4,若进栈序列为1,2,3,4,则()不可能是一个出栈序列。
3,2,1,4
3,2,4,1
4,2,3,1
4,3,2,1
1,2,3,4
1,3,2,4
5,若进栈队列的序列为1,2,3,4,则()是一个出队列序列。
3,2,1,4
3,2,4,1
4,2,3,1
4,3,2,1
1,2,3,4
1,3,2,4
6,若一个栈的输入序列是:
1,2,3,...,n,输出序列的第一个元素是n,则第i个输出元素是:
不确定
n-i
n-i+1
i
n-i-1
三编程题
1,以flag为标志位,写出循环队列中插入算法
2,以flag为标志位,写出循环队列中删除算法
4-2改写顺序栈的进栈成员函数Push(x),要求当栈满时执行一个stackFull()操作进行栈满处理。
其功能是:
动态创建一个比原来的栈数组大二倍的新数组,代替原来的栈数组,原来栈数组中的元素占据新数组的前MaxSize位置。
【解答】templatevoidstack:
:
push(constType&item){
if(isFull())stackFull();//栈满,做溢出处理
elements[++top]=item;//进栈
}
templatevoidstack:
:
stackFull(){
Type*temp=newType[2*maxSize];//创建体积大一倍的数组
for(inti=0;i<=top;i++)//传送原数组的数据
temp[i]=elements[i];
delete[]elements;//删去原数组
maxSize*=2;//数组最大体积增长一倍
elements=temp;//新数组成为栈的数组空间
}
4-3铁路进行列车调度时,常把站台设计成栈式结构的站台,如右图所示。
试问:
(1)设有编号为1,2,3,4,5,6的六辆列车,顺序开入栈式结构的站台,则可能的出栈序列有多少种?
(2)若进站的六辆列车顺序如上所述,那么是否能够得到435612,325641,154623和135426的出站序列,如果不能,说明为什么不能;如果能,说明如何得到(即写出"进栈"或"出栈"的序列)。
【解答】
(1)可能的不同出栈序列有种。
(2)不能得到435612和154623这样的出栈序列。
因为若在4,3,5,6之后再将1,2出栈,则1,2必须一直在栈中,此时1先进栈,2后进栈,2应压在1上面,不可能1先于2出栈。
154623也是这种情况。
出栈序列325641和135426可以得到。
3
5
6
2
2
4
4
4
4
1
1
1
1
1
1
1
1
33232325325325632564325641
5
3
4
4
1
2
2
2
2
6
1113135********213542135426
4-4试证明:
若借助栈可由输入序列1,2,3,…,n得到一个输出序列p1,p2,p3,…,pn(它是输入序列的某一种排列),则在输出序列中不可能出现以下情况,即存在i(提示:
用反证法)
【解答】
因为借助栈由输入序列1,2,3,…,n,可得到输出序列p1,p2,p3,…,pn,如果存在下标i,j,k,满足i¬i进栈,i出栈,j进栈,j出栈,k进栈,k出栈。
此时具有最小值的排在最前面pi位置,具有中间值的排在其后pj位置,具有最大值的排在pk位置,有pii进栈,i出栈,j进栈,k进栈,k出栈,j出栈。
此时具有最小值的排在最前面pi位置,具有最大值的排在pj位置,具有中间值的排在最后pk位置,有pi®i进栈,j进栈,j出栈,i出栈,k进栈,k出栈。
此时具有中间值的排在最前面pi位置,具有最小值的排在其后pj位置,有pj¯i进栈,j进栈,j出栈,k进栈,k出栈,i出栈。
此时具有中间值的排在最前面pi位置,具有最大值的排在其后pj位置,具有最小值的排在pk位置,有pk°i进栈,j进栈,k进栈,k出栈,j出栈,i出栈。
此时具有最大值的排在最前面pi位置,具有中间值的排在其后pj位置,具有最小值的排在pk位置,有pk
4-5写出下列中缀表达式的后缀形式:
(1)A*B*C
(2)-A+B-C+D
(3)A*-B+C
(4)(A+B)*D+E/(F+A*D)+C
(5)A&&B||!
(E>F){注:
按C++的优先级)
(6)!
(A&&!
((BD)))||(C【解答】
(1)AB*C*
(2)A-B+C-D+
(3)AB-*C+
(4)AB+D*EFAD*+/C+
(5)AB&&EF>!
||
(6)ABC||!
&&!
CE<||
4-7设表达式的中缀表示为a*x-b/x↑2,试利用栈将它改为后缀表示ax*bx2↑/-。
写出转换过程中栈的变化。
【解答】
步序
扫描项
项类型
动作
栈的变化
输出
0
☞'#'进栈,读下一符号
#
1
a
操作数
☞直接输出,读下一符号
#
a
2
*
操作符
☞isp('#')#*
a
3
x
操作数
☞直接输出,读下一符号
#*
ax
4
-
操作符
☞isp('*')>icp('-'),退栈输出
#
ax*
☞isp('#')#-
ax*
5
b
操作数
☞直接输出,读下一符号
#-
ax*b
6
/
操作符
☞isp('-')#-/
ax*b
7
x
操作数
☞直接输出,读下一符号
#-/
ax*bx
8
↑
操作符
☞isp('/')#-/↑
ax*bx
9
2
操作数
☞直接输出,读下一符号
#-/↑
ax*bx2
10
#
操作符
☞isp('↑')>icp('#'),退栈输出
#-/
ax*bx2↑
☞isp('/')>icp('#'),退栈输出
#-
ax*bx2↑/
☞isp('-')>icp('#'),退栈输出
#
ax*bx2↑/-
F结束
4-9假设以数组Q[m]存放循环队列中的元素,同时以rear和length分别指示环形队列中的队尾位置和队列中所含元素的个数。
试给出该循环队列的队空条件和队满条件,并写出相应的插入(enqueue)和删除(dlqueue)元素的操作。
【解答】
循环队列类定义
#include
templateclassQueue{//循环队列的类定义
public:
Queue(int=10);
~Queue(){delete[]elements;}
voidEnQueue(Type&item);
TypeDeQueue();
TypeGetFront();
voidMakeEmpty(){length=0;}//置空队列
intIsEmpty()const{returnlength==0;}//判队列空否
intIsFull()const{returnlength==maxSize;}//判队列满否
private:
intrear,length;//队尾指针和队列长度
Type*elements;//存放队列元素的数组
intmaxSize;//队列最大可容纳元素个数
}
构造函数
template
Queue:
:
Queue(intsz):
rear(maxSize-1),length(0),maxSize(sz){
//建立一个最大具有maxSize个元素的空队列。
elements=newType[maxSize];//创建队列空间
assert(elements!
=0);//断言:
动态存储分配成功与否
}
插入函数
template
voidQueue:
:
EnQueue(Type&item){
assert(!
IsFull());//判队列是否不满,满则出错处理
length++;//长度加1
rear=(rear+1)%maxSize;//队尾位置进1
elements[rear]=item;//进队列
}
删除函数
template
TypeQueue:
:
DeQueue(){
assert(!
IsEmpty());//判断队列是否不空,空则出错处理
length--;//队列长度减1
returnelements[(rear-length+maxSize)%maxSize];//返回原队头元素值
}
读取队头元素值函数
template
TypeQueue:
:
GetFront(){
assert(!
IsEmpty());
returnelements[(rear-length+1+maxSize)%maxSize];//返回队头元素值
}
4-10假设以数组Q[m]存放循环队列中的元素,同时设置一个标志tag,以tag==0和tag==1来区别在队头指针(front)和队尾指针(rear)相等时,队列状态为“空”还是“满”。
试编写与此结构相应的插入(enqueue)和删除(dlqueue)算法。
【解答】
循环队列类定义
#include
templateclassQueue{//循环队列的类定义
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;//队列最大可容纳元素个数
}
构造函数
template
Queue:
:
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,表示栈不空
}
删除函数
template
TypeQueue:
:
DeQueue(){
assert(!
IsEmpty());//判断队列是否不空,空则出错处理
front=(front+1)%m;//队头位置进1,队头指针指示实际队头的前一位置
tag=0;//标志改0,表示栈不满
returnQ[front];//返回原队头元素的值
}
读取队头元素函数
template
TypeQueue:
:
GetFront(){
assert(!
IsEmpty());//判断队列是否不空,空则出错处理
returnQ[(front+1)%m];//返回队头元素的值
}
4-11若使用循环链表来表示队列,p是链表中的一个指针。
试基于此结构给出队列的插入(enqueue)和删除(dequeue)算法,并给出p为何值时队列空。
【解答】
链式队列的类定义
templateclassQueue;//链式队列类的前视定义
templateclassQueueNode{//链式队列结点类定义
friendclassQueue;
private:
Typedata;//数据域
QueueNode*link;//链域
QueueNode(Typed=0,QueueNode*l=NULL):
data(d),link(l){}//构造函数
};
templateclassQueue{//链式队列类定义
public:
Queue():
p(NULL){}//构造函数
~Queue();//析构函数
voidEnQueue(constType&item);//将item加入到队列中
TypeDeQueue();//删除并返回队头元素
TypeGetFront();//查看队头元素的值
voidMakeEmpty();//置空队列,实现与~Queue()相同
intIsEmpty()const{returnp==NULL;}//判队列空否
private:
QueueNode*p;//队尾指针(在循环链表中)
};
队列的析构函数
templateQueue:
:
~Queue(){//队列的析构函数
QueueNode*s;
while(p!
=NULL){s=p;p=p→link;deletes;}//逐个删除队列中的结点
}
队列的插入函数
templatevoidQueue:
:
EnQueue(constType&item){
if(p==NULL){//队列空,新结点成为第一个结点
p=newQueueNode(item,NULL);p→link=p;
}
else{//队列不空,新结点链入p之后
QueueNode*s=newQueueNode(item,NULL);
s→link=p→link;p=p→link=s;//结点p指向新的队尾
}
}
队列的删除函数
templateTypeQueue:
:
DeQueue(){
if(p==NULL){cout<<"队列空,不能删除!
"<QueueNode*s=p;//队头结点为p后一个结点
p→link=s→link;//重新链接,将结点s从链中摘下
Typeretvalue=s→data;deletes;//保存原队头结点中的值,释放原队头结点
returnretvalue;//返回数据存放地址
}
队空条件p==NULL。
4-12若将一个双端队列顺序表示在一维数组V[m]中,两个端点设为end1和end2,并组织成一个循环队列。
试写出双端队列所用指针end1和end2的初始化条件及队空与队满条件,并编写基于此结构的相应的插入(enqueue)新元素和删除(dlqueue)算法。
【解答】
初始化条件end1=end2=0;
队空条件end1=end2;
队满条件(end1+1)%m=end2;//设end1端顺时针进栈,end2端逆时针进栈
循环队列类定义
#include
templateclassDoubleQueue{//循环队列的类定义
public:
DoubleQueue(int=10);
~DoubleQueue(){delete[]V;}
voidEnQueue(Type&item,constintend);
TypeDeQueue(constintend);
TypeGetFront(constintend);
voidMakeEmpty(){end1=end2=0;}//置空队列
intIsEmpty()const{returnend1==end2;}//判两队列空否
intIsFull()const{return(end1+1)%m==end2;}//判两队列满否
private:
intend1,end2;//队列两端的指针
Type*V;//存放队列元素的数组
intm;//队列最大可容纳元素个数
}
构造函数
template
DoubleQueue:
:
DoubleQueue(intsz):
end1(0),end2(0),m(sz){
//建立一个最大具有m个元素的空队列。
V=newType[m];//创建队列空间
assert(V!
=0);//断言:
动态存储分配成功与否
}
插入函数
template
voidDoubleQueue:
:
EnQueue(Type&item,constintend){
assert(!
IsFull());
if(end==1){
end1=(end1+1)%m;//end1端指针先进1,再按指针进栈
V[end1]