一、队列:一种可以实现先进先出的存储结构
1、队列可以分为:
- 链式队列(动态):用链表来实现
- 静态队列(顺序队列):用数组来实现(静态队列通常都必须是循环队列)
2、链式队列结构如下图:
3、静态队列一般都是循环队列,其目的是为了能重复使用数组的内存,减少内存的浪费。
(1)、如下图所示的循环队列: front = 0 ,rear = 5 ,此时循环队列已满。如下图的队列中最多可以存放 5 个元素,rear 处为空,不存放元素。
(2)、如果删除队列中的一个元素(队列只能从头 front 处删除元素),则对应的 front 、rear 位置如下图所示: front = 1 ,rear = 5
(3)、如果再插入一个元素,即入队(只能从循环队列的末尾 rear 插入元素),其结果如下。
此时 rear 的值小于 front 的值: front = 1 ,rear = 0
二、静态队列
1、静态队列的基本知识
(1)、静态队列 需要两个参数来确定,分别是front、rear
(2)、循环队列中两个参数的含义,在不同的场合中有不同的含义。
- 队列初始化:front 和 rear 都是零。
- 队列非空:front 代表的是队列的第一个元素;rear 代表的是队列的最后一个有效元素的下一个元素。
- 队列空:两个值相等,但不一定是零
(3)、循环队列的入队操作
【注】:由于循环队列是一个数组,当数组已满的时候,将无法加入新的元素。
- 将值存入 rear 所代表的位置
- 让 rear = ( rear + 1 ) % 数组的长度
(4)、循环队列出队操作
- front = (front + 1)% 数组的长度
(5)、循环队列为空
- front 和 rear 的值相等,即为空
(6)、循环队列已满
- 在循环队列中 front 的值可以比 rear 值大、小或者相等
- 如果 rear 和 front 紧挨着,则队列已满。用公式表示为:(rear + 1)% 数组长度 = front
2、应用实例
#include<iostream>
#include<malloc.h>
using namespace std;
typedef struct Queue
{
int * pBase;
int front;
int rear;
}QUEUE ;
// 初始化队列
void InitQueue(QUEUE* pQ)
{
// 动态申请一个大小为6的整型数组空间,并用pBase 指向它
pQ->pBase = (int *)malloc(sizeof(int) * 6);
pQ->front = 0;
pQ->rear = 0;
}
// 判断队列是否已满
bool IsFullQueue(const QUEUE* pQ)
{
if (pQ->front == (pQ->rear + 1) % 6)
return true;
else
{
return false;
}
}
// 判断队列是否为空
bool IsEmptyQueue(const QUEUE* pQ)
{
if (pQ->front == pQ->rear)
{
return true;
}
else
{
return false;
}
}
// 入队,将数据 val 加入到队列中
bool EnterQueue(QUEUE *pQ,int val)
{
// 首先判断队列是否已满,注意 pQ 本身就是一个地址
if (IsFullQueue(pQ))
{
return false;
}
else
{
pQ->pBase[pQ->rear] = val;
pQ->rear = (pQ->rear + 1) % 6; // 特别需要注意不能用 pQ->rear +=1
return true;
}
}
// 出队操作,pVal为指针类型,主函数才可以拿到该元素的值
bool OutQueue(QUEUE * pQ, int* pVal)
{
if (IsEmptyQueue(pQ))
{
cout << "队列为空,出队失败" << endl;
return false;
}
else
{
// 将出队的元素传给 *pVal
*pVal = pQ->pBase[pQ->front];
pQ->front = (pQ->front + 1) % 6;
return true;
}
}
// 遍历队列中的元素
void TraverseQueue(const QUEUE* pQ)
{
int i = pQ->front;
if (!IsEmptyQueue(pQ))
{
cout << "队列中的元素为:" << endl;
while (i != pQ->rear)
{
cout << pQ->pBase[i] << endl;
i = (i + 1) % 6;
}
}
else
{
cout << "队列为空" << endl;
}
}
int main()
{
QUEUE QL;
int val;// 用来接受出队的元素
InitQueue(&QL);
EnterQueue(&QL, 10);
EnterQueue(&QL, 20);
EnterQueue(&QL, 30);
EnterQueue(&QL, 40);
EnterQueue(&QL, 50);
TraverseQueue(&QL);
if (OutQueue(&QL,&val))
{
cout<<"出队的元素为:"<<val<<endl;
}
else
{
cout<<"出队失败"<<endl;
}
TraverseQueue(&QL);
cin.get();
}
运行结果如下图所示
3、具体应用
- 所有与时间有关的操作都与队列有关(队列是先进先出)