(PTA)数据结构(作业)6、队列

栈是后进先出的线性表(Last In First Out,LIFO),插入和删除的操作都在栈顶进行。

队列是先进先出的线性表(First In First Out,FIFO),插入在队尾进行,删除在队头进行。

循环队列的两种区别队满和队空的方式,

        1)少用一个元素,即当队列空间大小为m时,有m-1个元素就默认时队满。

                队空的条件:Q.front == Q.rear

                队满的条件:(Q.rear + 1)%m == Q.front

        2)专门设置一个标志来记录队列中的元素以区别队空还是队满。


目录

判断题

选择题

编程题

7-1 队的基本操作 (15 分)

7-2 队列的实现及基本操作 (10 分)

7-3 银行业务队列简单模拟 (15 分)

判断题

1、所谓“循环队列”是指用单向循环链表或者循环数组表示的队列。F

将顺序队列变为一个环状的空间,称这样的队列为循环队列。

2、在用数组表示的循环队列中,front值一定小于等于rear值。F

不一定,在循环队列中,有过出队情况之后,front不在头位置,当再入队超出数组长度之后,入队的元素会从头开始入队,此时rear值比front小。

3、An algorithm to check for balancing symbols in an expression uses a queue to store the partial expression.F

balancing symbols指的是一组匹配的符号,类似于圆括号,花括号,方括号。

用栈,因为括号这种匹配的符号是对称的,在找到是匹配的符号的时候,需要让匹配的字符出栈然后继续往下判断,而队列是没办法跟上一个入队的匹配后让它出队的。

{ [ ( ) ] }像这样,在找到匹配的符号之前一直是入栈操作,栈内是 { [ ( ,在找到右圆括号的时候,左圆括号出栈,而队列不行。

4、在对不带头结点的链队列作出队操作时,不会改变头指针的值。F

链队列出队是头指针指向下一个来使首元节点出队,入队是在链队列尾节点后插入一个新的节点。

5、队列是一种插入和删除操作分别在表的两端进行的线性表,是一种先进后出的结构。F

先进先出(FIFO),排队嘛。

6、不论是入队列操作还是入栈操作,在顺序存储结构上都需要考虑"溢出"情况。T

7、循环队列也存在着空间溢出问题。T

8、In a circular queue which is implemented by an array, the front value must always be no larger than the rear value.F

同第二题。

9、An algorithm to check for balancing symbols in an expression uses a stack to store the symbols.T

解释同第三题,刚好是正确的情况。

选择题

1、为解决计算机主机与打印机之间速度不匹配问题,通常设置一个打印数据缓冲区,主机将要输出的数据依次写入该缓冲区,而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是?

A.堆栈

B.队列

C.树

D.图

2、若已知一队列用单向链表表示,该单向链表的当前状态(含3个对象)是:1->2->3,其中x->y表示x的下一节点是y。此时,如果将对象4入队,然后队列头的对象出队,则单向链表的状态是:

A.1->2->3

B.2->3->4

C.4->1->2

D.答案不唯一

3、某队列允许在其两端进行入队操作,但仅允许在一端进行出队操作。若元素a、b、c、d、e依次入此队列后再进行出队操作,则不可能得到的出队序列是:

A.b a c d e

B.d b a c e

C.e c b a d

D.d b c a e

4、若用大小为6的数组来实现循环队列,且当前frontrear的值分别为0和4。当从队列中删除两个元素,再加入两个元素后,frontrear的值分别为多少?

A.2和0

B.2和2

C.2和4

D.2和6

注意大小为6的数组的下标最大是5,入队后 rear=(rear+1)%6

5、如果循环队列用大小为m的数组表示,且用队头指针front和队列元素个数size代替一般循环队列中的frontrear指针来表示队列的范围,那么这样的循环队列可以容纳的元素个数最多为:

A.m-1

B.m

C.m+1

D.不能确定

6、如果循环队列用大小为m的数组表示,队头位置为front、队列元素个数为size,那么队尾元素位置rear为:

A.front+size

B.front+size-1

C.(front+size)%m

D.(front+size-1)%m

从下标为0开始嘛,所以减一,拿几个数试试也知道。

7、在由n个元素组成的顺序存储的循环队列sq中,假定f和r分别为队头指针和队尾指针,则判断队满的条件是( )。

A.f ==(r+1)%n

B.(r - 1)%n==f

C.f == r

D.(f + 1)%n == f

在循环队列中,用 f == r 判断队空,即头尾指针指向同一个位置为空,用 f == (r+1)%n 判断队满,因为循环队列中有 n - 1个元素就认为事队满 , (r+1)%n 指的是尾指针的下一个位置,当尾指针的下一个位置是头指针的时候,即 f == ( r + 1)%n判断队满。

同时也可以知道,循环队列中尾指针指向尾节点的下一个位置。可以互相推导记忆。欸嘿。

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

A.可能是2

B.一定是2

C.可能是1

D.一定是1

第一个出的是3,栈内剩下1,2,此时可以进一个再出,也可以直接出栈,所以可能是2

9、循环顺序队列中是否可以插入下一个元素()。

A.与队头指针和队尾指针的值有关

B.只与队尾指针的值有关,与队头指针的值无关

C.只与数组大小有关,与队首指针和队尾指针的值无关

D.与曾经进行过多少次插入操作有关

是否可以插入下一个元素需要i判断队满 front == (rear+1)%n

10、判断一个循环队列QU(最多元素为MaxSize)为空的条件是()。

A.QU.front == QU.rear

B.QU.front != QU.rear

C.QU.front == (QU.rear + 1) % MaxSize

D.QU.front != (QU.rear + 1) % MaxSize

11、用单链表表示的链队的队头在链表的()位置。

A.链头

B.链尾

C.链中

D.均可以

出队时只需要让队头移向下一个位置即可。

而如果在队尾的话,因为时单链表,每次出队要重新遍历到倒数第二个来移动队头。

链中的话,队头前边的怎么出队呢?

12、设一个循环队列Q[maxSize]的队头指针为front,队尾指针为rear,队列最大容量为maxSize,此外该队列再没有其他数据成员,则队列的队满条件是( )。

A.Q.front == Q.rear

B.Q.front+Q.rear >= maxSize

C.Q.front == (Q.rear +1) % maxSize

D.Q.rear == (Q.f ront+1) % maxSize

13、现有队列 Q 与栈 S,初始时 Q 中的元素依次是{ 1, 2, 3, 4, 5, 6 }(1在队头),S 为空。若允许下列3种操作:(1)出队并输出出队元素;(2)出队并将出队元素入栈;(3)出栈并输出出栈元素,则不能得到的输出序列是:

A.1, 2, 5, 6, 4, 3

B.2, 3, 4, 5, 6, 1

C.3, 4, 5, 6, 1, 2

D.6, 5, 4, 3, 2, 1

14、在利用堆栈将下列哪个中缀表达式转换为后缀表达式过程中,堆栈的操作系列为:
push('*') 、push('(')、 push('+')、pop()、pop()、pop()、push('*')、pop()、push('+')、pop()

A.2*(3+4)*5+6

B.2*(3+4*5)+6

C.2*(3+4*5+6)

D.以上都是

开始的时候栈内为空,” * “ 入栈,此时栈内:  *

然后 “( ”优先级大于 “ * ”,所以“ (  ”入栈 ,此时栈内: * (

在遇到 “ )”时 “ ( ” 才会直接出栈运算直到 "( " 出栈, 所以 “ + ” 入栈 ,此时栈内: * ( +

然后找到 “ )” ,开始出栈,第一个出栈 “ + ”,3+4=7,此时栈内: * (

然后 “( ” 出栈,并没有运算,此时栈内: *

然后 “ * ” 与 “ * ” 优先级相同出栈 ,2*7 =14,栈内为空,

再入栈 “ * ” ,栈内为: *

遇到  “ + ” ,“ * ” 优先级大于 “ + ”,所以 “ * ”出栈 14 *5 =70,此时栈内为空,

“ + ”入栈,没有元素可以入栈,“ + ” 出栈 70+6=76。

15、在一个不带头结点的非空链式队列中,假设f和r分别为队头和队尾指针,则插入s所指的结点运算是( )。

A.f->next=s; f=s;

B.r->next=s; r=s;

C.s->next=s; r=s;

D.s->next=f; f=s;

链式队列插入在队尾

16、在一个不带头结点的非空链式队列中,假设f和r分别为队头和队尾指针,则删除结点的运算是( )。

A.r=f->next;

B.r=r->next;

C.f=f->next;

D.f=r->next

链式队列的删除操作在队头进行

17、若用一个大小为6的数组来实现循环队列,且当前rear和fornt的值分别为0和3。从当前队列中删除一个元素,再加入两个元素后,rear和front的值分别为( )。

A.1和5

B.2和4

C.4和2

D.5和1

删除一个元素,front = 3 + 1 = 4;加入两个元素 rear = 0 + 2 = 2;别看反了就行

18、在一个顺序存储的循环队列中,若队尾指针指向队尾元素的后一个位置,则队头指针一般指向队头元素的( )。

A.前一个位置

B.后一个位置

C.当前位置

D.后两个位置

19、在一个顺序循环队列中,若队头指针指向队头元素的当前位置,则队尾指针一般指向队尾元素的( )位置。

A.后两个

B.后一个

C.当前

D.前一个

20、依次在初始为空的队列中插入元素a,b,c,d以后,紧接着做了两次删除操作,此时的队头元素是( )。

A.a

B.b

C.c

D.d

21、在少用一个元素空间的循环队列(m为最大队列长度)是满队列的条件( )。

A.rear==front

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

C.(rear+1)==front

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

编程题

7-1 队的基本操作 (15 分)

给定一个初始为空的队(队存储空间长度为10)和一系列进队、出队操作,请编写程序输出经过这些操作后队中的元素。队中元素值均为整数。(采用循环队列完成,禁用一个空间方法)

输入格式:

输入第1行为1个正整数n,表示操作个数;

第2行为给出的n个整数,非0元素表示进队,且此非0值即为进队元素,0元素表示出队。

输出格式:

第一行按出队顺序输出所有出队元素,以一个空格隔开;如果队空时做出队操作会输出"EMPTY",如果队满时做进队操作会输出"FULL"。

第二行中输出队中所有元素,以一个空格隔开。

末尾均有一个空格。

输入样例:

12
3 1 2 0 0 -1 0 0 0 4 5 0

输出样例:

3 1 2 -1 EMPTY 4 
5 

#include <iostream>

using namespace std;

#define MAXSIZE 10 //队列可能达到的最大长度

typedef struct
{
    int* base;//存储空间的基地址
    int front;//头指针
    int rear;//尾指针
}SqQueue;

void InitQueue(SqQueue& Q)//初始化循环队列
{
    Q.base = new int[MAXSIZE]; //为队列分配一个最大容量为MAXSIZE的数组空间
    if (!Q.base) return ;  //存储分配失败
    Q.front = Q.rear = 0;   //将头指针和尾指针置为0,队列为空
    return ;
}

int QueueLength(SqQueue Q)//求循环队列的长度
{
    return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;//返回循环队列的长度
}

int EnQueue(SqQueue& Q, int e)//入队
{
    if ((Q.rear + 1) % MAXSIZE == Q.front)//若尾指针在循环意义上加 1 后等于头指针,表明队满。
    {
        cout << "FULL ";
        return 0;
    }
    Q.base[Q.rear] = e;//新元素插入队尾
    Q.rear = (Q.rear + 1) % MAXSIZE; //队尾指针加1
    return 1;
}

void DeQueue(SqQueue& Q, int& e)
{
    if (Q.front == Q.rear) //队空
    {
        cout << "EMPTY ";
        return;
    }

    e = Q.base[Q.front]; //保存队头元素
    cout << e<<" ";
    Q.front = (Q.front + 1) % MAXSIZE; // 队头指针加1
    return;
}

int main()
{
    int n,i,m;
    SqQueue queueA; //声明SqQueue结构体 命名为queueA
    InitQueue(queueA);//初始化循环队列
    
    int temp;
    cin >> n;
    i = 0;
    while (i<n)
    {
        cin >> m;
        if (m != 0)
        {
            EnQueue(queueA, m);
            
        }
        else
        {
            DeQueue(queueA, temp);
        }
        i++;
    }
    cout << endl;
    while (queueA.front != queueA.rear)
    {
        cout << queueA.base[queueA.front] << " ";
        queueA.front = (queueA.front +1)%MAXSIZE;
    }
    return 0;
}

7-2 队列的实现及基本操作 (10 分)

给定一个初始为空的队列和一系列入队、出队操作,请编写程序输出每次出队的元素。队列的元素值均为整数。

输入格式:

输入第1行为1个正整数n,表示操作个数;接下来n行,每行表示一个操作,格式为1 d或0。1 d表示将整数d入队,0表示出队。n不超过20000。

输出格式:

按顺序输出每次出队的元素,每个元素一行。若某出队操作不合法(如在队列空时出队),则对该操作输出invalid。

输入样例:

7
1 1
1 2
0
0
0
1 3
0

输出样例:

1
2
invalid
3



#include <iostream>

using namespace std;

#define MAXSIZE 20000 //队列可能达到的最大长度

typedef struct
{
    int* base;//存储空间的基地址
    int front;//头指针
    int rear;//尾指针
}SqQueue;

void InitQueue(SqQueue& Q)//初始化循环队列
{
    Q.base = new int[MAXSIZE]; //为队列分配一个最大容量为MAXSIZE的数组空间
    if (!Q.base) return;  //存储分配失败
    Q.front = Q.rear = 0;   //将头指针和尾指针置为0,队列为空
    return;
}

int QueueLength(SqQueue Q)//求循环队列的长度
{
    return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;//返回循环队列的长度
}

int EnQueue(SqQueue& Q, int e)//入队
{
    if ((Q.rear + 1) % MAXSIZE == Q.front)//若尾指针在循环意义上加 1 后等于头指针,表明队满。
    {
        cout << "invalid";
        return 0;
    }
    Q.base[Q.rear] = e;//新元素插入队尾
    Q.rear = (Q.rear + 1) % MAXSIZE; //队尾指针加1
    return 1;
}

void DeQueue(SqQueue& Q, int& e)//出队
{
    if (Q.front == Q.rear) //队空
    {
        cout << "invalid" <<endl;
        return;
    }
    e = Q.base[Q.front]; //保存队头元素
    cout << e << endl;
    Q.front = (Q.front + 1) % MAXSIZE; // 队头指针加1
    return;
}

int main()
{
    int n, i;
    SqQueue queueA; //声明SqQueue结构体 命名为queueA
    InitQueue(queueA);//初始化循环队列

    int temp;
    cin >> n;
    i = 0;
    int j, k;
    while (i < n)
    {
        cin >> j;
        if (j == 1)
        {
            cin >> k;
            EnQueue(queueA, k);
        }
        else if(j == 0)
        {
            DeQueue(queueA, temp);
        }
        i++;
    }
    return 0;
}

7-3 银行业务队列简单模拟 (15 分)

设某银行有A、B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 —— 即当A窗口每处理完2个顾客时,B窗口处理完1个顾客。给定到达银行的顾客序列,请按业务完成的顺序输出顾客序列。假定不考虑顾客先后到达的时间间隔,并且当不同窗口同时处理完2个顾客时,A窗口顾客优先输出。

输入格式:

输入为一行正整数,其中第1个数字N(≤1000)为顾客总数,后面跟着N位顾客的编号。编号为奇数的顾客需要到A窗口办理业务,为偶数的顾客则去B窗口。数字间以空格分隔。

输出格式:

按业务处理完成的顺序输出顾客的编号。数字间以空格分隔,但最后一个编号后不能有多余的空格。

输入样例:

8 2 1 3 9 4 11 13 15

输出样例:

1 3 2 9 11 4 13 15

 解题思路:

其实都是基本操作,就是A队列出栈两次B队列出栈一次,A优先出栈罢了,主要问题在处理最后一个元素后边不能有空格。

我是在按每次出队的时候判断下一次还有没有出队的事件来判断是否打印后边空格。

也可以当成前导空格,刚开始不打印空格,设置一个标志flag,让标志flag在0的时候不打印前导空格,存在出队事件之后标志flag++,然后flag>0的时候都打印前导空格的情况就好了。


#include <iostream>

using namespace std;

#define MAXSIZE 1000 //队列可能达到的最大长度

typedef struct
{
	int* base;//存储空间的基地址
	int front;//头指针
	int rear;//尾指针
}SqQueue;

void InitQueue(SqQueue& Q)//初始化循环队列
{
	Q.base = new int[MAXSIZE]; //为队列分配一个最大容量为MAXSIZE的数组空间
	if (!Q.base) return;  //存储分配失败
	Q.front = Q.rear = 0;   //将头指针和尾指针置为0,队列为空
	return;
}

int QueueLength(SqQueue Q)//求循环队列的长度
{
	return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;//返回循环队列的长度
}

int EnQueue(SqQueue& Q, int e)//入队
{
	if ((Q.rear + 1) % MAXSIZE == Q.front)//若尾指针在循环意义上加 1 后等于头指针,表明队满。
	{
		return 0;
	}
	Q.base[Q.rear] = e;//新元素插入队尾
	Q.rear = (Q.rear + 1) % MAXSIZE; //队尾指针加1
	return 1;
}

bool DeQueue(SqQueue& Q, int& e)//出队
{
	if (Q.front == Q.rear) //队空
	{
		return false;
	}
	e = Q.base[Q.front]; //保存队头元素
	cout << e;
	Q.front = (Q.front + 1) % MAXSIZE; // 队头指针加1
	return true;
}

bool GetQueueNull(SqQueue& Q)
{
	if (Q.front == Q.rear)  return true;//队空
	else return false;
}

int main()
{
	int n;
	SqQueue queueA; //声明SqQueue结构体 命名为queueA
	InitQueue(queueA);//初始化循环队列
	SqQueue queueB; //声明SqQueue结构体 命名为queueB
	InitQueue(queueB);//初始化循环队列

	int temp;
	int i, j;
	cin >> i;
	j = 0;
	while (j < i)
	{
		cin >> n;
		if (n % 2 == 1)
		{
			EnQueue(queueA, n);
		}
		else
		{
			EnQueue(queueB, n);
		}
		j++;
	}

	while (!GetQueueNull(queueA) || !GetQueueNull(queueB))
	{
		if (DeQueue(queueA, temp))
		{
			if (!GetQueueNull(queueA))cout << " ";
		}
		if (DeQueue(queueA, temp))
		{

			if (!GetQueueNull(queueB))cout << " ";
		}
		if (DeQueue(queueB, temp))
		{
			if (!GetQueueNull(queueA) || !GetQueueNull(queueB))
				cout << " ";
		}

	}
	return 0;
}

  • 8
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值