【数据结构C++之看懂就这一篇】队列:顺序队列,循环队列,链队列

大家好,我是追忆,欢迎各位大佬前来指教。
本期呢我们将把我对队列的理解讲述给大家,谢谢大家的支持,观看。
我的博客空间:追忆
在这里插入图片描述


在这里插入图片描述

前言

我们可以想象一下我们在餐厅排队吃饭的时候是如何进行的?
应该是谁先到,先排进队伍中,谁先打到饭,谁先走(当然啊,这是在无人插队的情况下)。
故队列也与此相同,谁先进,谁就先出。


一、定义

队列:队列是一种先进先出(FIFO) 的线性表。 在表一端插入,在另一端删除。
其入队和出队示例如图所示:
我们把a1,a2,到an入队:
在这里插入图片描述
此时我们把a1称为队头,an称为队尾。
然后我们把a1出队:
在这里插入图片描述

此时a2就成为了队头。
由此我们引出队列的定义:只能在表的一端(队尾)进行插入,在另一端(队头)进行删除运算的线性表。
而对于逻辑结构来说:与线性表相同,仍为一对一关系。
那么什么是一对一关系呢?
答案是

① 存在一个唯一的被称为“第一个”的数据元素;
② 存在一个唯一的被称为“最后一个”的数据元素;
③ 除第一个元素外,每个元素均有唯一一个直接前驱;
④ 除最后一个元素外,每个元素均有唯一一个直接后继。

存储结构也与线性表相同:用顺序队列或链队存储均可。
运算规则:先进先出(FIFO)。

二、队列的基本结构

由于队列有两种存储方式,所以我们在这里用一种笼统的定义方式来创建一个队列,我们先考虑一下建立一个队列都需要什么?
数据元素。
我们要进行哪几项操作?

  1. 构建空队列
  2. 销毁队列
  3. 清空队列
  4. 判断是否为空
  5. 求队列长度
  6. 入队
  7. 出队
  8. 遍历

所以我们可以这样建立队列

ADT Queue {
数据对象:D= {a;|a;∈ElemSet,i= 1,2,-.,,n, n≥0}
数据关系:R ={<ai-1,ai>|ai-1,ai∈D,i= 1,2,-,n}
基本操作:
	  (1)  InitQueue (&Q)         //构造空队列
      (2) DestroyQueue (&Q)   //销毁队列
      (3) ClearQueue (&Q)       //清空队列
      (4) QueueEmpty(Q)          //判空. 空--TRUE,
      (5) QueueLength(Q)         //取队列长度
      (6) GetHead (Q,&e)         //取队头元素
      (7) EnQueue (&Q,e)        //入队列
      (8) DeQueue (&Q,&e)     //出队列
      (9) QueueTraverse(Q)       //遍历
}ADT Queue

由此,我们可以开始对队列进行编写程序了。

三、顺序队列

事先声明:由于顺序队列存在的问题过大,我们不再深入了解,故我不会过多的解释。相关操作会在循环队列中实现。

1.定义

在探讨顺序队列如何定义的时候,我们不妨考虑一下顺序表是如何定义的?
如下:

typedef struct
ElemType *base; //基指针
int Length;//顺序表长度
} SqList;

根据给出的顺序表我们可以推断出顺序队列该如何定义?
首先,肯定要有一个基指针让我们去动态的申请一块连续的空间。
而对于顺序表长度而言,对队列意义是不大的。
我们要考虑一下,顺序队列是如何操作的?
从队尾入队,从队头出队。
根据这个原因,我们是不是要知道队列的队头和队尾的位置。
故应该有头指针和尾指针,但我们要考虑一下,是否需要知道队头和队尾的位置?
我认为是不需要的,我们其实可以把顺序队列看成一个数组,知道下标,我们就知道相应的元素了。
故我们应该如下定义:

typedef struct {
   QElemType *base;  //初始化的动态分配存储空间
   int  front;            //头指针   
   int  rear;             //尾指针
}SqQueue;  

那么为了方便我们理解,在这里我有个小问题:假设我们此时创立了一个队列Q,我们该如何访问队头元素?
我们知道 Q.front是不是队头元素的下标,知道其下标,我们该如何知道对应的元素信息?
在这里我们可以利用数组来回答问题:
假设我们知道数组a,我们此时来个定义:

int *p=a;

如果我们想访问i所处位置的元素,我们可以直接用p来得到

p[i]=a[i];

故我们只需要知道指针和对应的下标来得之相应的元素。也就是

Q.base[Q.front]

可以得出队头元素。

2.操作实现

如果我们此时创建一个顺序队列Q:
在这里插入图片描述
我们可以看出最开始的时候 队头和队尾都指向同一个元素,也就是:

Q.rear=Q.base=0;

①入队

我们该如何实现入队操作呢?
入队只能在队尾实现,我们现在把J1进行入队操作:
如图
在这里插入图片描述
此时,下一步应该怎么做呢?
要记住,是从队尾入,队头不变,故应该

Q.rear++

也就是
在这里插入图片描述
此时我们把J2再入队,也是同样的操作:

在这里插入图片描述
在这里插入图片描述
队头不变,队尾++。
这是入队的操作。代码实现也就是:

Q.base[Q.rear++]=x;

②出队

考虑完入队,我们再考虑一下出队:
出队是从哪里出的?
答案是从队头出队,队尾不变
此时有一个队列Q:
在这里插入图片描述
我们此时要进行出队操作,肯定是把J1进行出队操作:
在这里插入图片描述
此时J1已经出队,Q.front变,还是Q.rear变呢?
答案是:
在这里插入图片描述
Q.front往后移,Q.rear不变。也就是

Q.front--

故此时出队操作应该是:

x=Q.base[Q.front++];

③存在的一些问题

在这里插入图片描述
此时队列已经满了,如果我们此时再进行入队操作的话,就会造成溢出,由于此时队列本身就是满的,我们称为真溢出
而对于下述情况来说:
在这里插入图片描述
此时队列并没有满,但是此时Q.rear处于最后一位, 在进行入队操作的话,就会造成溢出,但此时队列并没有满,我们称为:假溢出
那么由以上两种情况来看,无论队列是否为满,都会造成溢出的情况,那么如何解决这种问题呢?
我们是不是可以把第二种情况当成一个小纸条,小纸条的上面写满了,我们是不是可以从下面写,然后再粘在一起,形成一个圆,也叫循环队列。

四、循环队列(首尾连接)

1.前提引入

如图
在这里插入图片描述
此为循环队列示意图。
注意:所谓的循环队列真的是让其在内存存储中成为一个环状的嘛?
答案当然是不是啦!!!
数据在内存中存储不可能是环状的,是线性的,我们在此只是用一种方法来让队列看起来像一个环状,但其还是顺序存储。
但此时还有一个问题,如图
在这里插入图片描述
如果此时我们将J5,J6进行出队,Q.front就会从4变成5,再从5变成0,如图:
在这里插入图片描述

那么此时有个问题:我们怎么把5变成0呢?
我们可以从上图看出:数值都是0-5,所以我们只要保证运算出来是从0·5就行。那么6个数怎么得出此结果呢?
取模!!!

2.如何取模

取模即为取余数,取到的值永远不会大于除数。
例如,队列总大小为6 (7 下标0~5)
正常入队:Q. rear=Q. rear+ 1
循环入队:Q.rear= (Q.rear+1) % 6
正常出队::Q.front=Q.front+1
循环出队:Q.front= (Q.front+ 1) % 6

3.空队和满队一样如何解决

那是否还会由有其他问题呢?
我们使用队列时会出现三种情况:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看出a和c的时候,rear=front
那么我们该如何区别呢?
这里我将会给出两种解决方案:

  • 少用一个元素空间
  • 另外设一个标志以区别队空、队满

①少用一个元素空间

在这里插入图片描述
如图,此时Q.rear+1=Q.front。
如果此时Q.front=0,Q.rear=5,队列已满,如何表示?
简单,还是利用取模。

(Q.rear+1)%M==Q.front

即:
队空:

Q.front==Q.rear

队满:

(Q.rear+1 )%M==Q.front

②另外设一个标志以区别队空、队满

如图
在这里插入图片描述
在这里插入图片描述

当队列为空时,我们设置一个标志flag,使其为0
当队列不为空时,我们使其等于1

2.队列操作的实现

①初始化

初始化即把原先定义的东西给一一赋值。
我们之前是如何定义的?

#define MAXQSIZE  100  //最大长度
typedef struct {
   QElemType *base;  //初始化的动态分配存储空间
   int  front;            //头指针   
   int  rear;             //尾指针
}SqQueue;  

现在我们要做的是,为其一一赋值,为指针分配空间。
也就是进行以下操作:

bool InitQueue (SqQueue &Q){
    Q.base =new QElemType[MAXQSIZE]; 
   if(!Q.base) 
   return false;
    Q.front=Q.rear=0;
    return true;
}

②求循环队列的长度

在这里插入图片描述
如果只根据上图,只使用队尾减去队头就可以得到队长了,但仅仅就这样可以吗?
答案当然是不对的。如下图
在这里插入图片描述
这时,用队尾减去队头是不可以的,是负数。
这时我们就要找一个通用公式了:

先看第一个图:4-0=4
第二个图: 2-4=-2
如果此时让第二个图加上长度可以不?试一下
-2+6=4;得到结果了
但是并不是通用的,因为图一再加上长度的话:4+6=10;不对
再考虑
取模
对喽
此时我们加上长度后再进行取模运算的话
图一:10%6=4;对
图二:4%6=4.;对

则公式为:(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
则程序可写为:

int  QueueLength(SqQueue Q){
    return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;                             
 }

③入队

入队该如何入,我们之前也说过,队尾后移,队头不变。但此时我们要用循环队列的时候,要用取模运算,进行后移。
此时要考虑什么时候入队?
队不满的时候,这时我们要从两个方面考虑了:

I少用一个元素空间

什么时候队满?
上文提到过
在这里直接给出程序:

bool EnQueue(SqQueue &Q,QElemType e){
    if((Q.rear+1)%MAXQSIZE==Q.front)  return false;
    Q.base[Q.rear]=e;
    Q.rear=(Q.rear+1)%MAXQSIZE;
     return true;
}
II另外设一个标志以区别队空、队满

在上面我们提到

flag=1:队列中有元素
flag=0: 队列为空

故此时的程序可以如下:

bool EnQueue(SqQueue &Q,QElemType e)
{
	if((Q.flag==1) && (Q.rear==Q.front))
{	cout<<"队列已满"<<endl;
	return false;
}
else { Q.base[Q.rear] =e;
Q.rear = (Q.rear+1) % MAXQSIZE;
}
if(Q.flag==0) 
Q.flag=1;
//队列已不空
return true;
}

从上述程序中我们看到flag前面有个Q.可以得到我已经把flag定义到结构体中了。

④出队

出队如何出?
从队头出,队尾不变,队头后移。
什么时候不能出队?
队为空,有两种情况

I少用一个元素空间

什么时候队空?
上文提到过
在这里直接给出程序:

bool DeQueue (SqQueue &Q,QElemType &e){
   if(Q.front==Q.rear) return false;
   e=Q.base[Q.front];
   Q.front=(Q.front+1)%MAXQSIZE;
   return true;
}
II另外设一个标志以区别队空、队满

什么时候队空?
上文提到过
程序给出:

bool DeQueue(SqQueue &Q,QElemType &e)
{
if(Q.flag==0)
{
cout<<"队列为空"<<endl;
return false; 
}
else{ 
e=Q.base[Q.front];
Q.front=(Q.front+1) % MAXQSIZE;
if(Q.front==Q.rear)
Q.flag=0;1/空队
return true;
}

⑤取队头元素

取队头元素非常简单,只需Q.base[Q.front],但仅仅如此可以吗?
当然不可以:我们要判断是否为空队:

QElemType GetHead (SqQueue Q)
{
   if(Q.front!=Q.rear)
       return Q.base[Q.front];
}

⑥遍历队列

非常简单,但需注意,遍历的时候,队头,队尾都不能进行移动,故此时需要再定义一个。

void TraverseQueue(SqQueue Q) {  
    int i = Q.front;  
    while (i != Q.rear) {  
        cout << Q.base[i] << " ";  
        i = (i + 1) % MAXQSIZE;  
    }  
    cout << endl;  
}  

3.整体程序

下面将用int类型示例

①少用一个元素空间

#include <iostream>
using namespace std;
typedef int QElemType;
#define MAXQSIZE  100  //最大长度
typedef struct {
	QElemType* base;  //初始化的动态分配存储空间
	int  front;            //头指针   
	int  rear;             //尾指针
}SqQueue;
//初始化
bool InitQueue(SqQueue& Q) {
	Q.base = new QElemType[MAXQSIZE];
	if (!Q.base)
		return false;
	Q.front = Q.rear = 0;
	return true;
}
//入队
bool EnQueue(SqQueue& Q, QElemType e) {
	if ((Q.rear + 1) % MAXQSIZE == Q.front)  return false;
	Q.base[Q.rear] = e;
	Q.rear = (Q.rear + 1) % MAXQSIZE;
	return true;
}
//出队
bool DeQueue(SqQueue& Q, QElemType& e) {
	if (Q.front == Q.rear) return false;
	e = Q.base[Q.front];
	Q.front = (Q.front + 1) % MAXQSIZE;
	return true;
}
//求长度
 int  QueueLength(SqQueue Q){
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
 }
//取队头元素
QElemType GetHead(SqQueue Q)
{
	if (Q.front != Q.rear)
		return Q.base[Q.front];
}
//遍历元素
void TraverseQueue(SqQueue Q) {
	int i = Q.front;
	while (i != Q.rear) {
		cout << Q.base[i] << " ";
		i = (i + 1) % MAXQSIZE;
	}
	cout << endl;
}
int main() {
	SqQueue Q;
	QElemType e;
	int n, i;
	// 初始化队列  
	InitQueue(Q);
	cout << "请输入您要插入元素的个数:";
	cin >> n;
	// 入队操作  
	cout << "请输入您要插入的元素:";
	for (i = 0; i < n; i++)
	{
		cin >> e;
		EnQueue(Q, e);
	}
	// 遍历队列  
	cout << "队列元素:";
	TraverseQueue(Q);
	cout << "队列长度:" << QueueLength(Q) << endl;
	
	// 出队操作  
	if (DeQueue(Q, e)) {
		cout << "出队元素:" << e << endl;
	}

	// 遍历队列  
	cout << "队列元素:";
	TraverseQueue(Q);

	// 释放队列占用的内存  
	delete[] Q.base;

	return 0;
}

在这里插入图片描述
②另外设一个标志以区别队空、队满

#include <iostream>
using namespace std;
typedef int QElemType;
#define MAXQSIZE  100  //最大长度
typedef struct {
	QElemType* base;  //初始化的动态分配存储空间
	int  front;            //头指针   
	int  rear;             //尾指针
	int flag;
}SqQueue;
//初始化
bool InitQueue(SqQueue& Q) {
	Q.base = new QElemType[MAXQSIZE];
	if (!Q.base)
		return false;
	Q.flag = Q.front = Q.rear = 0;
	return true;
}
//入队
bool EnQueue(SqQueue& Q, QElemType e)
{
	if ((Q.flag == 1) && (Q.rear == Q.front))
	{
		cout << "队列已满" << endl;
		return false;
	}
	else {
		Q.base[Q.rear] = e;
		Q.rear = (Q.rear + 1) % MAXQSIZE;
	}
	if (Q.flag == 0)
		Q.flag = 1;
	//队列已不空
	return true;
}
//出队
bool DeQueue(SqQueue& Q, QElemType& e)
{
	if (Q.flag == 0)
	{
		cout << "队列为空" << endl;
		return false;
	}
	else {
		e = Q.base[Q.front];
		Q.front = (Q.front + 1) % MAXQSIZE;
		if (Q.front == Q.rear)
			Q.flag = 0;  // 空队
			return true;
	}
}
//求长度
 int  QueueLength(SqQueue Q){
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
 }
//取队头元素
QElemType GetHead(SqQueue Q)
{
	if (Q.front != Q.rear)
		return Q.base[Q.front];
}
//遍历元素
void TraverseQueue(SqQueue Q) {
	int i = Q.front;
	while (i != Q.rear) {
		cout << Q.base[i] << " ";
		i = (i + 1) % MAXQSIZE;
	}
	cout << endl;
}
int main() {
	SqQueue Q;
	QElemType e;
	int n, i;
	// 初始化队列  
	InitQueue(Q);
	cout << "请输入您要插入元素的个数:";
	cin >> n;
	// 入队操作  
	cout << "请输入您要插入的元素:";
	for (i = 0; i < n; i++)
	{
		cin >> e;
		EnQueue(Q, e);
	}
	// 遍历队列  
	cout << "队列元素:";
	TraverseQueue(Q);
	cout << "队列长度:" << QueueLength(Q) << endl;
	
	// 出队操作  
	if (DeQueue(Q, e)) {
		cout << "出队元素:" << e << endl;
	}

	// 遍历队列  
	cout << "队列元素:";
	TraverseQueue(Q);

	// 释放队列占用的内存  
	delete[] Q.base;

	return 0;
}

在这里插入图片描述

五、链队

前提引入

关于链队,我们可以参考链表也就是我的上一篇博文:链表
在这里插入图片描述

我们考虑一下如何入队和出队?
从队尾插入,从队头进行出队也就是删除。
所以说在声明一个链队列的时候,仅仅是声明一个简单的链表可不可以?
当然是不行的。
我问不仅要设置一个头指针用来出队,还要设置一个尾指针用来入队。
现在又要考虑一个问题:尾指针指向尾部,拿头指针是指向头节点还是首元结点?
指向头节点是比较好的,因为我们指向首元结点的时候,首元结点在出队的时候会一直变,头指针一直需要后移,而指向头结点是不需要一直后移的。
我们看一下链队图片
在这里插入图片描述
它的每个节点包含的内容和链表是一致的。即数据域和指针域。

1.定义

故应该如下定义:

typedef struct QNode{
   QElemType   data;
   struct Qnode  *next;
}QNode, *QueuePtr;

而我上面也提到了要附设一个头指针和尾指针来方便我们进行操作,而他们应该是什么类型的呢?
在链表中我们就提到过,指针应该是指向什么类型,就是什么类型,那么头指针和尾指针指向的是?
结点。对喽。
故应该如下定义:

typedef struct {
   QueuePtr  front;            //队头指针   
   QueuePtr  rear;             //队尾指针
}LinkQueue;  

我们假设给一个LinkQuene Q
那么我们该如何取队头元素呢?
很简单

e=Q.front->data;

2.操作实现

前提引入

链队有以下情况
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看一下如何入队,Q.rear后移,而Q.front->next指向x所在的结点,
而如何出队呢?
从队头出队,只需要让Q.front->next从指向x到指向y。

①初始化

我一直在说,初始化就是对结构中的元素赋初值,分配空间,所以非常简单:
首先我们要给头指针和尾指针分配空间:

Q.front=Q.rear=new QNode;

而对于数据域,我们先不为其赋值,因为我们不知道。
然后再为指针赋值,也就是:

 Q.front->next=NULL;

完整程序:

bool InitQueue (LinkQueue &Q){
  	Q.front=Q.rear=new QNode;
    if(!Q.front) return false;
    Q.front->next=NULL;
     return true;
}

②销毁

在这里插入图片描述
我们要将所有节点给delete,该如何做?
在链表中,我们重新定义了一个指针,来代替头指针,来进行交替后移,在这里也是如此:

QueuePtr p=Q.front;
Q.front=Q.front->next;
delete p;

但是有必要嘛?
我认为是没有必要的,因为我们最开始是定义了两个指针,我们只需要两个指针交替后移就行了,完整程序如下:

bool DestroyQueue (LinkQueue &Q){
   while(Q.front){
      Q.rear=Q.front->next;
      delete Q.front;
      Q.front=Q.rear;   }    
   return true;
}

③判断是否为空

很简单,直接给出程序:

bool QueueEmpty (LinkQueue Q){
    return (Q.front==Q.rear);                             
 }

④求队头元素

在这里插入图片描述
队头元素是什么?
Q.front->next指向结点的数据,也就是

  e=Q.front->next->data;

在取队头元素的时候,切记链队一定不能为空,所以我们要先判断:
完整程序:

bool GetHead (LinkQueue Q, QElemType &e){
   if(Q.front==Q.rear) return false;
   e=Q.front->next->data;
   return true;v
}

⑤入队

入队是从哪里入?
队尾。
那么我们现在有一个x,我们要先申请一块空间:

QueuePtr p=new QNode;

然后把这个结点里的指针域和数据域进行赋值,在赋值前我们要判断申请空间是否成功:

 if(!p) return false;
    p->data=e; 
    p->next=NULL;

为什么此时p->next=NULL呢?
因为我们是从尾部插入(可以参考链表的尾插法),它的下一个一定为空。
然后我们需要把这个结点连接到链队中。

  Q.rear->next=p;
   Q.rear=p;

完整程序:

bool EnQueue(LinkQueue &Q,QElemType e){
  	QueuePtr p=new QNode;
    if(!p) exit(OVERFLOW);
    p->data=e; p->next=NULL;
    Q.rear->next=p;
    Q.rear=p;
    return true;
}

思考:如果想要实现调用一次入队函数,使n个元素入队,该怎么办?
两种解决方式:

  • 在主函数内使用循环
  • 在函数体中传一个n,嵌套在循环中

⑥出队

在这里插入图片描述

如图,出队只能从队头出,此时只能把x出队。
在这里插入图片描述

为什么要另设一个p?
因为我们要delete
现在开始出队:
我们可以直接让Q.front->next指向y结点,也就是:

 Q.front->next=p->next;

但是在进行操作前,我们一定要先判断是否为空队。故完整程序如下:

bool DeQueue (LinkQueue &Q,QElemType &e){
   if(Q.front==Q.rear) return false;
   QueuePtr p=Q.front->next;
   e=p->data;
   Q.front->next=p->next;
   if(Q.rear==p) Q.rear=Q.front;
   delete p;
   return true;
}

会有一个疑问:为什会有 if(Q.rear==p) Q.rear=Q.front;这条语句呢?
我们要考虑一下:
在这里插入图片描述
如果此时把y出队的时候,尾指针是不是会悬空?
悬空就会造成程序错误,故要进行一些操作。

⑦遍历

遍历也是非常简单,但我们也要注意我们此时的头指针和尾指针都不能移动,所以我们要重新第一个指针来移动去访问各个结点:

void TraversalQueue(LinkQueue Q) {  
    QueuePtr p = Q.front->next;  
    while (p) {  
        cout << p->data << " ";  
        p = p->next;  
    }  
    cout << endl;  
}  

完整程序

#include <iostream>
using namespace std;
typedef int QElemType;
typedef struct QNode {
	QElemType   data;
	struct QNode* next;
}QNode, * QueuePtr;
typedef struct {
	QueuePtr  front;            //队头指针   
	QueuePtr  rear;             //队尾指针
}LinkQueue;
//初始化
bool InitQueue(LinkQueue& Q) {
	Q.front = Q.rear = new QNode;
	if (!Q.front) return false;
	Q.front->next = NULL;
	return true;
}
//销毁
bool DestroyQueue(LinkQueue& Q) {
	while (Q.front) {
		Q.rear = Q.front->next;
		delete Q.front;
		Q.front = Q.rear;
	}
	return true;
}
//判空
bool QueueEmpty(LinkQueue Q) {
	return (Q.front == Q.rear);
}
//取队头元素
bool GetHead(LinkQueue Q, QElemType& e) {
	if (Q.front == Q.rear) 
		return false;
	e = Q.front->next->data;
	return true; 
}
//入队
bool EnQueue(LinkQueue& Q, QElemType e) {
	QueuePtr p = new QNode;
	if (!p) exit(OVERFLOW);
	p->data = e; p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;
	return true;
}
//出队
bool DeQueue (LinkQueue &Q,QElemType &e){
   if(Q.front==Q.rear) return false;
   QueuePtr p=Q.front->next;
   e=p->data;
   Q.front->next=p->next;
   if(Q.rear==p) Q.rear=Q.front;
   delete p;
   return true;
}
//遍历
void TraversalQueue(LinkQueue Q) {
	QueuePtr p = Q.front->next;
	while (p) {
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}
int main() {
	LinkQueue Q;
	QElemType e;
	int n, i;
	// 初始化队列  
	if (!InitQueue(Q)) {
		cout << "初始化失败!" << endl;
		return 1;
	}
	cout << "请输入您要插入元素的个数:";
	cin >> n;
	// 入队操作  
	cout << "请输入元素:";
	for (i = 0; i < n; i++)
	{
		cin >> e;
		EnQueue(Q, e);
	}

	// 遍历队列  
	cout << "遍历队列: ";
	TraversalQueue(Q);

	// 出队操作  
	if (DeQueue(Q, e)) {
		cout << "出队元素: " << e << endl;
	}

	// 遍历队列  
	cout << "遍历队列 : ";
	TraversalQueue(Q);
	DestroyQueue(Q);
	return 0;
}

在这里插入图片描述

总结

以上就是我对队列的理解,至于为什么没有删除和插入这两个操作,在最开始的前提引入中我就提到,队列就像排队,排队过程中如果插队和被删除是一种不文明的行为。
谢谢大家的观看以及支持。

评论 59
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值