【浅谈数据结构】队列的基本函数与操作
作者:互联网
文章目录
1、定义及基本运算
定义:
队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表
说明:
(1)、允许删除的一端称为队头(Front)。
(2)、允许插入的一端称为队尾(Rear)。
(3)、当队列中没有元素时称为空队列。
(4)、队列亦称作先进先出(First In First Out)的线性表,简称为FIFO表。
注意:
队列的修改是依先进先出的原则进行的。新来的成员总是加入队尾(即不允许"加塞"),每次离开的成员总是队列头上的(不允许中途离队),即当前"最老的"成员离队。
【例】在队列中依次加入元素a1,a2,…,an之后,a1是队头元素,an是队尾元素。退出队列的次序只能是a1,a2,…,an。
2、队列的基本运算
(0)、队列的定义
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QueueNode;
//在这里使用了一个结构体对于 head tail 进行封装,便于后续使用
typedef struct Queue
{
QueueNode* head;//头指针,队非空时指向队头元素
QueueNode* tail;//尾指针,队非空时指向队尾元素的下一位置
}Queue;
(1)、QueueInit(Q)
置空队。构造一个空队列Q。
(2)、QueueEmpty(Q)
判队空。若队列Q为空,则返回真值,否则返回假值。
(3)、 QueueFull(Q)
判队满。若队列Q为满,则返回真值,否则返回假值。
注意:
此操作只适用于队列的顺序存储结构。
(4)、EnQueue(Q,x)
若队列Q非满,则将元素x插入Q的队尾。此操作简称入队。
(5)、 DeQueue(Q)
若队列Q非空,则删去Q的队头元素,并返回该元素。此操作简称出队。
(6)、QueueFront(Q)
若队列Q非空,则返回队头元素,但不改变队列Q的状态。
一、顺序队列
(1)、顺序队列的定义
队列的顺序存储结构称为顺序队列,顺序队列实际上是运算受限的顺序表。
(2)、 顺序队列的表示
① 和顺序表一样,顺序队列用一个向量空间来存放当前队列中的元素。
② 由于队列的队头和队尾的位置是变化的,设置两个指针front和rear分别指示队头元素和队尾元素在向量空间中的位置,它们的初值在队列初始化时均应置为0。
(3)、 顺序队列的基本操作
① 入队时:将新元素插入rear所指的位置,然后将rear加1。
② 出队时:删去front所指的元素,然后将front加1并返回被删元素。
注意:
① 当头尾指针相等时,队列为空。
② 在非空队列里,队头指针始终指向队头元素,尾指针始终指向队尾元素的下一位置。
二、循环队列
顾名思义,就是充分利用一段内存空间的队列
typedef Sturet{
int front; //头指针,队非空时指向队头元素
int rear; //计数器,记录队中元素总数
DataType cnt[QueueSize]//计数器,记录队中元素总数
}CirQueue;//循环队列的别名
循环队列的基本运算
① 置队空
void InitQueue(CirQueue *Q)
{
Q->front=Q->rear=0;
Q->count=0; //计数器置0
}
② 判队空
int QueueEmpty(CirQueue *Q)
{
return Q->count==0; //队列无元素为空
}
③ 判队满
int QueueFull(CirQueue *Q)
{
return Q->count==QueueSize; //队中元素个数等于QueueSize时队满
}
④ 入队
void EnQueue(CirQueuq *Q,DataType x)
{
if(QueueFull((Q))
Error("Queue overflow"); //队满上溢
Q->count ++; //队列元素个数加1
Q->data[Q->rear]=x; //新元素插入队尾
Q->rear=(Q->rear+1)%QueueSize; //循环意义下将尾指针加1
⑤ 出队g
DataType DeQueue(CirQueue *Q)
{
DataType temp;
if(QueueEmpty((Q))
Error("Queue underflow"); //队空下溢
temp=Q->data[Q->front];
Q->count--; //队列元素个数减1
Q->front=(Q->front+1)&QueueSize; //循环意义下的头指针加1
return temp;
}
三、链队列
队列的链式存储结构简称为链队列。它是限制仅在表头删除和表尾插入的单链表。(不一定非要使用单链表)
和链栈类似,无须考虑判队满的运算及上溢。
基本运算
①、置空队
void InitQueue(LinkQueue *Q)
{
Q->front=Q->rear=NULL;
}
②、判队空
intQueueEmpty(LinkQueue *Q)
{
return Q->front==NULL&&Q->rear==Null;
//实际上只须判断队头指针是否为空即可
}
③、入队
void EnQueue(LinkQueue *Q,DataType x)
{//将元素x插入链队列尾部
QueueNode *p=(QueueNode *)malloc(sizeof(QueueNode));//申请新结点
p->data=x; p->next=NULL;
if(QueueEmpty(Q))
Q->front=Q->rear=p; //将x插入空队列
else { //x插入非空队列的尾
Q->rear->next=p; //*p链到原队尾结点后
Q->rear=p; //队尾指针指向新的尾
}
}
④、出队
DataType DeQueue (LinkQueue *Q)
{
DataType x;
QueueNode *p;
if(QueueEmpty(Q))
Error("Queue underflow");//下溢
p=Q->front; //指向对头结点
x=p->data; //保存对头结点的数据
Q->front=p->next; //将对头结点从链上摘下
if(Q->rear==p)//原队中只有一个结点,删去后队列变空,此时队头指针已为空
Q->rear=NULL;
free(p); //释放被删队头结点
return x; //返回原队头数据
}
⑤、取队头元素
DataType QueueFront(LinkQueue *Q)
{
if(QueueEmpty(Q))
Error("Queue if empty.");
return Q->front->data;
}
标签:队头,浅谈,队列,元素,front,数据结构,rear,指针 来源: https://blog.csdn.net/GuLeng______/article/details/122735424