1.栈的“先进后出”特性是指( A)。
A.最后进栈的元素总是最先出栈
B.同时进行进栈和出栈操作时,总是进栈优先
C.每当有出栈操作时,总要先进行一次进栈操作
D.每次出栈的元素总是最先进栈的元素
2.给定一个足够大的空栈,有4个元素的进栈次序为A、B、C、D,则以C、D开头的出栈序列的个数为(A )。
A.1
B.2
C.3
D.4
3.若元素a、b、c、d、e、f依次进栈,允许进栈、退栈的操作交替进行,但不允许连续3次退栈工作,则不可能得到的出栈序列是(D )。
A.dcebfa
B.cbdaef
C.bcaefd
D.afedcb
4.一个栈的进栈序列是a、b、c、d、e,则栈的不可能的输出序列是( C)。
A.edcba
B.decba
C.dceab
D.abcde
5.当用一个数组data[0…n-1]存放栈中元素时,栈底最好(C )。
A.设置在data[0]处
B.设置在data[n-1]处
C.设置在data[0]或data[n-1]处
D.设置在data数组的任何位置
解析:C、栈中元素的逻辑关系呈现线性关系,这样有两个端点,最好将栈底设置在某个端点data[0]或data[n-1]处,从而方便栈运算算法的设计。
6.若一个栈用数组data[1…n]存储,初始栈顶指针top为n+1,则以下元素x进栈的正确操作是(C )。
A.top++; data[top]=x;
B.data[top]=x; top++;
C.top–; data[top]=x;
D.data[top]=x; top–;
7.若一个栈用数组data[1…n]存储,初始栈顶指针top为0,则以下元素x进栈的正确操作是( A)。
A.top++; data[top]=x;
B.data[top]=x; top++;
C.top–; data[top]=x;
D.data[top]=x; top–;
8.在设计链栈时,通常采用单链表作为链栈,而不采用双链表作为链栈,其准确的原因是(A )。
A.栈中元素是顺序存取的,用单链表就足够了
B.栈中元素是随机存取的,用单链表就足够了
C.双链表运算较单链表更复杂
D.双链表存储密度较单链表低
9.栈和队列的不同点是(C )。
A.都是线性表
B.都不是线性表
C.栈只能在同一端进行插入删除操作,而队列在不同端进行插入删除操作
D.没有不同点
10.设循环队列qu中数组data的下标是0~N-1,其队头、队尾指针分别为f和r(f指向队首元素的前一位置,r指向队尾元素),元素x进队的操作是( B);qu.data[qu.rear]=x。
A.qu.rear++
B.qu.rear=(qu.rear+1)%N
C.qu.front++;
D.qu.front=(qu.front+1)%N
11.设循环队列qu中数组data的下标是0~N-1,其队头、队尾指针分别为f和r(f指向队首元素的前一位置,r指向队尾元素),元素x出队的操作是( D);x=qu.data[qu.front]。
A.qu.rear++
B.qu.rear=(qu.rear+1)%N
C.qu.front++;
D.qu.front=(qu.front+1)%N
12.若某循环队列有队首指针front和队尾指针rear,在队不空时出队操作仅会改变(A )。
A.front
B.rear
C.front和rear
D.以上都不对
13.通常设置循环队列qu的队空条件(front队首指针指向队首元素的前一位置,rear队尾指针指向队尾元素)是(D )。
A.(qu.rear+1)%MaxSize==(qu.front+1)%MaxSize
B.(qu.rear+1)%MaxSize= =qu.front+1
C.(qu.rear+1)%MaxSize= =qu.front
D.qu.rear= =qu.front
14.设循环队列的存储空间为a[0…20],且当前队头指针(f指向队首元素的前一位置)和队尾指针(r指向队尾元素)的值分别为8和3,则该队列中元素个数为(C )。
A.5
B.6
C.16
D.17
解析:C、这里MaxSize=21,其中的元素个数=(r-f+MaxSize)%MaxSize=16。
15.假设用一个不带头节点的单链表表示队列,队头在链表的(A )位置。
A.链头
B.链尾
C.链中
D.以上都可以
16.与顺序队相比,链队(D )。
A.优点是可以实现无限长队列
B.优点是进队和出队时间性能更好
C.缺点是不能进行顺序访问
D.缺点是不能根据队首和队尾指针计算队的长度
解析: D、尽管链队总是采用动态分配方式,其长度也受内存大小的限制,也不可能实现无限长队列。顺序队和链队的进队和出队操作时间均为O(1)。顺序队和链队都可以进行顺序访问。在顺序队中可以通过队头和队尾指针计算队中元素个数,而链队不能。
17.若用一个大小为6的数组来实现循环队列,且当前rear和front的值分别为0和3,当从队列中删除一个元素,再加入两个元素后,rear和front的值分别为( B)。
A.1和5
B.2和4
C.4和2
D.5和1
18.一个循环队列中用data[0…n-1]数组保存队中元素,另设置一个队尾指针rear和一个记录队中实际元素个数的变量count,则该队中最多可以存放的元素个数是( B)。
A.n-1
B.n
C.(rear+n) % n
D.(n-rear) % n
19.已知循环队列存储在一维数组A[0…n-1]中,且队列非空时front和rear分别指向队头元素和队尾元素。若初始时队列空,且要求第一个进入队列的元素存储在A[0]处,则初始时front和rear的值分别是(B )。
A.0,0
B.0,n-1
C.n-1,0
D. n-1,n-1
20.在循环队列中,元素的排列顺序( A)。
A.由元素进队的先后顺序确定
B.与元素值的大小有关
C.与队头和队尾指针的取值有关
D.与队中数组大小有关
1 .设输入元素为1、2、3、P和A,进栈次序为123PA,元素经过栈后到达输出序列,当所有元素均到达输出序列后,有哪些序列可以作为高级语言的变量名?
解:AP321,P321A,P32A1,P3A21,PA321。
2 .在以下几种存储结构中,哪个最适合用作链栈?并说明理由。
(1)带头节点的单链表
(2)不带头节点的循环单链表
(3)带头节点的双链表
解:(1)带头节点的单链表。栈中元素是顺序存取的,用单链表就足够了,需要带头节点使第一个节点的操作和表中其他节点的操作相一致,无需进行特殊处理,无论栈是否为空,都有一个头节点,因此空栈与非空栈的处理也就统一了。
3 .简述以下算法的功能:
void fun(int a[],int n)
{ int i=0,e;
SqStack *st;
InitStack(st);
for (i=0;i<n;i++)
Push(st,a[i]);
i=0;
while (!StackEmpty(st))
{ Pop(st,e);
a[i++]=e;
}
DestroyStack(st);
}
解:将a数组中的元素进栈,然后又出栈,存放在a数组中,使a数组中的顺序反序。
4 .假设表达式中允许包含3种括号:圆括号、方括号和大括号。设计一个算法采用顺序栈判断表达式中的括号是否正确配对。
bool Match(char exp[],int n)
{
bool match=true;
int i=0;
char e;
SqList *st;
InitStack(st);
while(i<n&&match)
{
if(exp[i]=='('||exp[i]=='['||exp[i]=='{') //如果exp等于小括号,方括号或者大括号,则放入栈中
Push(st,exp[i]);
else if(exp[i]==')'||exp[i]==']'||exp[i]=='}')
{
if(GetTop(st,e)==true) //判断栈中是否为空
{
if(e!=')'||e!=']'||e!='}') match=false;
else Pop(st,e); //若配对,则将左边的括号出栈
}
else match=false; //若栈为空,则不配对,返回错误
}
i++;
}
if(!StackEmpty(st)) match=false;
DestoryStack(st);
return match;
}
5 .假设以I和O分别表示入栈和出栈操作,栈的初态和终态均为空,进栈和出栈的操作序列可表示为仅由I和O组成的序列。15
(1)下面所示的序列中哪些是合法的?
A.IOIIOIOO B.IOOIOIIO C.IIIOIOIO D.IIIOOIOO
解:A,D
(2)通过对(1)的分析,写出一个算法判定所给的操作序列是否合法。若合法返回true;否则返回false(假设被判定的操作序列已存入一维数组中)。
bool Match(char exp[],int n)
{
bool match=true;
int i=0;
char e;
SqList *st;
InitStack(st);
while(i<n&&match)
{
if(exp[i]=='|')
Push(st,exp[i]);
else
{
if(GetTop(st,e)==true)
{
Pop(st,e);
}
else mtach=false;
}
i++;
}
if(!StackEmpty(st)) match=false;
DestoryStack(st);
return match;
}
6 .以1、2、3、…、n的顺序进队,可以产生的出队序列有多少种?
解:可能的出队列只有一种,即1,2,3,…,n。
7 .什么是循环队列?采用什么方法实现循环队列?
解:把数组的前端和后端连接起来,形成一个环形的顺序表,即把存称队列元素的表从逻辑上看成一个环称为环形队列或循环队列。可以通过逻辑方式实现循环队列。
8 .链队相对于顺序队而言,有何优势和不足?
解:链队采用动态分配方式,对队满的情况可以不考虑,可以防止数据泄露。但是链队不能根据队首和队尾指针计算队的长度。
9 .对于循环队列,设计求其中元素个数的算法。
int Queue(QuType *qu,int MaxSize)
{
int count;
count=(rear-front+MaxSize)%MaxSize;
return count;
}
10 .对于顺序队来说,如果知道队尾元素的位置和队列中的元素个数,则队头元素所在位置显然是可以计算的。也就是说,可以用队列中的元素个数代替队头指针。设计出这种循环顺序队的初始化、入队、出队和判空算法。
循环顺序队初始化
void InitQueue(QuType *&qu)
{
qu=(QuType *)malloc(sizeof(QuType));
q->front=0;
q->rear=0;
}
循环顺序队入队
bool enQueue(QuType *&qu,int e)
{
if(qu->count==MaxSize) return false;
int rear;
rear=(qu->front+qu->count)%MaxSize;
rear=(rear+1)%MaxSize;
qu->data[qu->rear]=e;
qu->count++;
return true;
}
循环顺序队出队
bool deQueue(QuType *&qu,int e)
{
if(qu->count==0) return false;
front=(front+1)%MaxSize;
e=qu->data[qu->front];
qu->count--;
return true;
}
循环顺序队判空算法
bool QueueEmpty(QuType *qu)
{
return (qu->count==0);
}