线性表-----队列

1、基本概念

  • 队列是只允许在一端进行插入而在另一段进行删除线性表
  • 队头:允许删除的一端
  • 队尾:允许插入的一端
  • 空队列:没有任何元素的空表
    在这里插入图片描述

队列是操作受限的线性表,因此不是任何对线性表的操作都可以作为队列的操作,比如,不可以随便读取队列中间某个数据

2、顺序队列

队列的顺序实现是指分配一块连续存储单元存放队列中的元素,并设两个指针front和rear分别指向队头和队尾元素的元素。队尾rear指针指向队尾元素的下一个位置(也可以让rear指向队尾元素,front指向队头元素的前一个位置),为什么要这样处理呢?当队列中只有一个元素是,rear和front将会相等,处理起来很麻烦。

  • 初始状态(队空条件):front==rear==0
  • 进队:不满时,送值到队尾,队尾rear加1
  • 出队:不空时,取队头元素,队头front加1
/*
顺序队列
*/
typedef struct {
	ElemType data[MaxSize];
	int front, rear;
}SqQueue;

在这里插入图片描述
当此时队列的状态为上图的d时,在入队,现任此时rear再加一会出现溢出,但这种溢出并不是真正的溢出,在data数组里依然有位置存放数据,所以这是一种假溢出

2、循环队列

把存储队列元素的表从逻辑上看作是一个环,称为循环队列。当用循环队列时,上面顺序队列出现假溢出的问题就能解决

  • 初始时,Q.front=Q.rear=0
  • (出队) front指针加1:Q.front=(Q.front+1)%MaxSize
  • (入队)rear指针加1:Q.rear=(Q.rear+1)%MaxSize
  • 队列长度:(Q.rear-Q.front+MaxSize)%MaxSize
  • 出队入队指针按顺时针方向进1

如何判断队列空和队满呢?

法1:牺牲一个单元来区分队空和队满,入队时少用一个队列单元,这是个普遍的做法,约定以:队头指针在队尾指针的下一个位置作为队满的标志

  • 队满:(Q.rear+1)%MaxSize==Q.front
  • 队空条件:Q.front==Q.rear(注意和顺序队列区分开,Q.front==Q.rear==0)
  • 队中元素个数:(Q.rear-Q.front+MaxSize)%MaxSize

在这里插入图片描述
法2:类型中增设表示元素个数的数据成员。这样,

  • 队空的条件为Q.size==0
  • 队满:Q.size==MaxSize

法3:类型增设tag数据成员,以区分队满还是队空。tag等于0时,若因删除导致QQ.front==Q.rear,则为对空;tag等于1时,若因插入导致Q.front==Q.rear,则为队满

3、链式队列

队列的链式存储结构,其实就是线性表的单链表,只不过需要加点限制,只能在表尾插入,表头删除。
在这里插入图片描述

typedef struct {
	ElemType data;
	struct LinkNode* next;
}LinkNode;
typedef struct {
	LinkNode* front, * rear;
}LinkQueue;
  • 当 Q.front ==NULL && Q.rear==NULL时,链式队列为空

4、双端队列

双端队列是指允许两端都可以进行入队和出队操作的队列,将队列的两端分别称为前端和后端,不再是队头和队尾,其逻辑结构依然是线性结构。
在这里插入图片描述
输出受限的双端队列:允许在一端进行插入和删除,但在另一端只允许插入的双端队列被称为输出受限的双端队列
在这里插入图片描述
输入受限的双端队列:允许在一端进行插入和删除,但另一端只允许删除的双端队列称为输入受限的双端队列
在这里插入图片描述

发布了168 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_41683305/article/details/104417472