队列(Quene)是一种特殊的线性表,它只能在表的一端插入元素,在另一端删除元素。
入队:在表的一端插入元素;
出队:在表的另一端删除元素;
特性:先进先出(First In First Out, FIFO)
InitQuene(&Q):初始化队列,构造一个空队列Q;
QueneEmpty(Q):判断队列是否为空,若为空返回false,否则返回true;
EnQuene(&Q, e) :入队,若队列未满,则把e插入,使之成为新的队尾;
DeQuene(&Q, &e):出队,若队列非空,则删除队头元素,并用e返回;
GetHead(Q, &e):取队头,若队列非空,将队头元素赋值给e;
队列的顺序实现是指分配一块连续的存储单元存放队列中的元素,并附设两个指针:队头指针front指向队头元素,队尾指针rear指向队尾元素。
队列的顺序存储结构如下:
#define MAXSIZE 100 //队列可能达到的最大长度
typedef struct
{
ElemType data[MAXSIZE]; //存放队列元素
int front, rear; //队头指针和队尾指针
}SqQueue;
初始状态(队为空):Q.front == Q.rear == 0。
进队:队不满时,先送值到队尾元素,再将尾指针加1;
出队:队不空时,先取队头元素值,再将队头指针加1;
(a)队列的初始状态,Q.front == Q.rear == 0成立,该条件可以作为判断队列是否为空的条件。
(b)元素e, d, c, b, a依次入队,此时队满
(c)元素a出队,队头指针Q.front减1。
(d)元素 b, c, d依次出队,队头指针和队尾指针指向同一个元素,此时队列不能插入新的队尾元素,但是data数组中依然存在可以存放元素的空位置,所以这种现象称为“假溢出”。
由于顺序队列可能会发生“假溢出”现象,所以必须使用一种更好的数据存储结构:循环队列。将顺序队列臆造为一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。当队首指针Q.front = MAXSIZE - 1后,再前进一个位置就自动到0,这可以利用除法取余运算(%)来实现。
初始状态:Q.front = Q.rear = 0
队首指针进1:Q.front = (Q.front + 1) % MAXSIZE
队尾指针进1:Q.rear = (Q.rear + 1) % MAXSIZE
队列长度:(Q.rear + MAXSIZE - Q.front) % MAXSIZE
出队入队时:指针都按顺时针方向进1
队空与队满:使用Q.front == Q.rear来判断队空,但是当(d1)时也有Q.front == Q.rear。
一般有两种方法判断队满或队空:
(1)少用一个元素空间,即队列空间大小为m时,有m - 1个元素就认为队满。判空的条件不变,即首尾指针相同时队空。而当尾指针在循环意义上加1后等于头指针则认为队满。此时,循环队列中队空与队满的条件是:
队空的条件:Q.front == Q.rear
队满的条件:(Q.rear + 1) % MAXSIZE == Q.front
(2)另设一个标志位(tag)判断队满还是队空。tag等于0时,若因删除导致Q.front == Q.rear,则为队空;tag等于1时,若因插入导致Q.front == Q.rear,则为队满
(1)初始化
void InitQuene(SqQuene &Q){
Q.rear = Q.front = 0;
}
(2)判空
bool QueneEmpty(SqQuene Q){
if(Q.rear == Q.front) return true;
else return false;
}
(3)入队
bool EnQuene(SqQuene &Q, ElemType e){
if((Q.rear + 1) % MAXSIZE == Q.front) return false;
Q.data[Q.rear] = x;
Q.rear = (Q.rear + 1) % MAXSIZE;
return true;
}
(4)出队
bool DeQuene(SqQuene &Q, ElemType e){
if(Q.rear == Q.front) return false;
e = Q.data[Q.front];
Q.front = (Q.front + 1) % MAXSIZE;
return true;
}
原文:https://www.cnblogs.com/boiledblood/p/14379055.html