目录
一、队列概念
队列是另一种线性表,队列只允许在一端进行插入操作,删除在另一端。插入的一端为队尾,删除的一端为队头。队列的特点:先进先出。
二、队列的运算操作
1.队列的初始化:InitQueue(q)
初始条件:队列q不存在
2.入队操作:InQueue(q,x)
初始条件:队列q存在
采用尾插法,将元素x插在队尾
3.出队操作:OutQueue(q)
初始条件:队列q存在并且q非空
4.读队头元素:FrontQueue(q)
初始条件:q存在且非空
读队头元素并返回该值,队列不变
5.判断队列空操作:Empty(q)
初始条件:q存在
三、队列的顺序存储结构
利用一个连续的存储单元依次存放队列中的数据元素。定义两个指示器,rear指向队尾,front指向队头,插入元素(入队)时rear加一,删除元素(出队)时front加一,front始终指向实际队头元素的前一个位置。
(1)顺序队列的类型定义:
typedef struct
{
ElemType elem[MAXSIZE];
int front,rear; //定义两个指示器,rear指向队尾,front指向队首
}SeQueue;
(2)队列的初始化:
SeQueue*sq=(SeQueue*)malloc(sizeof(SqQueue));
sq->rear=sq->front=-1; //置空队
(3)
队列的数据区域:
sq->elem[0]——sq->elem[MAXSIZE-1]
(4)入队操作:
sq->rear++; //让指向队尾的指针先指向下一个新的位置,再接受插入的数据元素
sq->elem[sq->rear]=x;
(5)出队操作:
sq->front++;
x=sq-elem[sq->front]; //自定义一个数据类型接受出队的元素
四、假溢出问题
图(d)队尾指针已经移到最后的位置,但队列并未满,因为队尾入,队头出,此时造成假溢出问题。
五、循环队列
为解决假溢出问题,充分利用存储空间。可采用循环队列,将elem[0]与elem[MAXSIZE-1]相连接。
1.头尾连接通过取余运算:
入队时:sq->rear=(sq->rear+1)%MAXSIZE;
出队时:sq->front=(sq->front+1)%MAXSIZE;
2.循环对列中队满与队空条件相同的问题
通过观察图可以发现,无论是队满还是队空,sq->rear=sq->front,此时造成无法判断是队空还是队满。
解决方法:少用一个元素空间,使队满时的条件为(sq->rear)%MAXSIZE=sq->front;队空条件为:sq->rear=sq->front;
3.循环对列基本运算如下:
typedef struct //定义一个结构
{
Elemtype elem[MAXSIZE];
int front, rear;
}CSeQueue;
//循环队列的初始化
CSeQueue* InitCSeQueue()
{
CSeQueue* cs;
cs = (CSeQueue*)malloc(sizeof(CSeQueue));
cs->front = cs->rear = MAXSIZE - 1; //置空队
return cs;
}
//入队
int InCSeQueue(CSeQueue* cs,Elemtype x)
{
if ((cs->rear) % MAXSIZE + 1 == ->front) //入队前判断队是否满
return;
cs->rear = (cs->rear + 1) % MAXSIZE;
cs->elem[cs->rear] = x;
return TRUE;
}
//出队
int PushCSeQueue(CSeQueue* cs,Elemtype*x)
{
if (cs->rear == cs->front) //出队判断队是否为空
return;
cs->front = (cs->front + 1) % MAXSIZE;
*x = cs->elem[cs->front];
return TRUE;
}
六、队的链式存储结构
用户无法预计所需要的队列的最大空间,可采用链式结构存储队列。采用带头结点的单链表表示队列,定义一个指向链队列的指针包括指向队的队头指针和队尾指针。队头指针始终指向头结点,队尾指针始终指向最后一个元素的结点。满足先进先出的特点,采用尾插法插入数据元素。
(1)队列链式结构的初始化
typedef struct node
{
DataType data;
struct node* next;
}QNode;
typedef struct //将指向链式队列的队头队尾指针放在一起
{
struct node* front;
struct node* rear;
}LQNode;
LQNode* InitQNode() //初始化
{
LQNode* p,QNode*q;
p = (LQNode*)malloc(sizeof(LQNode)); //为头尾指针申请结点
q= (QNode*)malloc(sizeof(QNode)); //为单链表的头指针申请结点
q->next =NULL;
p->front = p->rear = q;
return p;
}
(2)入队
int InQNode(LQNode* p, DataType x)
{
QNode* q;
if((q = (QNode*)malloc(sizeof(QNode)))==NULL); //申请一个结点空间是否申请成功
return;
q->data = x;
q->next = NULL;
p->rear->next = q;
p->rear= q;
return TRUE;
}
(3)出队
int PushQNode(LQNode* p,DataType* x)
{
QNode* q;
if (p->front == p->rear) //判断队是否为空
return;
q = p->front->next;
*x = q->data;
p->front->next = q->next;
free(q);
if (p->front->next == NULL) //如果只有一个元素时,出队后队空,需要修改队尾指针指向
p->rear = p->front;
return TRUE;
}
(4)判队空
int EmptyQNode(LQNode* p)
{
if (p->front == p->rear)
return 0;
else
return 1;
}