基本概念
1.只允许在一端进行插入操作,在另一端进行删除操作的线性表;
2.队尾:允许插入(入队、进队)的一端;
3.队头:允许删除(出队)的一端;
4.特性:先进先出
5.例子:银行排队、键盘缓冲区、操作系统的作业调度
01顺序队列
1.设置队头、队尾变量 rear 、front;
2.入队rear+1、出队rear-1;
3.约定:front指向队头元素的前一个位置,rear指向队尾元素的位置;
02循环队列
1.假溢出:队列向数组高端移动,元素插入到数组下标的最大位置后,数组低端还有空闲空间;
2.解决方案:头尾相接的循环结构;
3.操作语句:rear = (rear + 1)%QueueSize;
4.队空:front = rear;
5.队满:(rear + 1) % QueueSize = front;(浪费一个数组元素空间;
实现:
#include<iostream>
using namespace std;
const int queue_Size = 100;
template <typename DataType>
class CirQueue
{
public:
CirQueue(); //循环队列构造函数
~CirQueue(); //循环队列析构函数
void EnQueue(DataType x); //入队操作
DataType DeQueue(); //出队操作
DataType GetHead(); //取队头元素
int IsEmpty(); //判空操作
private:
DataType data[queue_Size];
int rear, front;
具体实现:
(1)构造函数:将rear和front同时指向数组的某一位置(一般为高端);
(2)析构函数:无需
(3)入队操作:判断队满情况,rear循环意义上加1后插入数据
template <typename DataType>
void CirQueue<DataType>::EnQueue(DataType x)
{
if ((rear + 1) % queue_Size == front) throw"上溢";
rear = (rear + 1) % queue_Size;
data[rear] = x;
}
(4)出队操作:判断队空情况,front循环意义上加1,读取返回
template <typename DataType>
DataType CirQueue<DataType>::DeQueue()
{
if (rear == front)throw"下溢";
front = (front + 1) % queue_Size;
return data[front];
}
(5)取队头元素:判断是否为队空,否则返回结果
template <typename DataType>
DataType CirQueue<DataType>::GetHead()
{
if (rear == front)throw"下溢";
return data[(front + 1) % queue_Size]; //注意不改变front 指针
}
(6)判空操作:front 是否等于 rear;
03链队列
1.加头结点:空队列与非空队列一致;
2.设队头指针指向头结点,队尾指针指向终端结点;
实现:
#include <iostream>
using namespace std;
template <typename DataType>
struct Node //结点
{
DataType data;
Node<DataType>* next;
};
template<typename DataType>
class LinkQueue
{
public:
LinkQueue(); //链队列构造函数
~LinkQueue(); //链队列析构函数
void EnQueue(DataType x); //入栈操作
DataType DeQueue(); //出栈操作
DataType GetHead(); //取队头元素
int IsEmpty(); //判空操作
private:
Node<DataType>* front, * rear;
}
(1)构造函数:申请头结点,队头指针与队尾指针均指向头结点
template<typename DataType>
LinkQueue<DataType>::LinkQueue()
{
Node<DataType>* first = nullptr;
first = new Node<DataType>;
first->next = nullptr;
rear = front = first;
}
(2)析构函数
template<typename DataType>
LinkQueue<DataType>::~LinkQueue()
{
Node<DataType>* p = front->next;
while (front->next != nullptr)
{
front->next = p->next;
delete p;
p = front->next;
}
}
(3)入队操作
template<typename DataType>
void LinkQueue<DataType>::EnQueue(DataType x)
{
Node<DataType>* add;
add = new Node<DataType>; //申请插入结点
add->data = x;
add->next = nullptr;
rear->next = add;
rear = add;
}
(4)出队操作:注意队列长度等于1的情况
template<typename DataType>
DataType LinkQueue<DataType>::DeQueue()
{
DataType x;
Node<DataType>* p = nullptr;
if (rear == front)throw "下溢";
p = front->next;
x = p->data;
front->next = p->next;
if (p->next == nullptr)
rear = front;
delete p;
return x;
}
(5)取队头元素:返回第一个元素结点的数据域,即:front->next->data;
(6)判空操作:front是否等于rear;
循环队列与链队列比较
1.时间复杂度均为O(1);
2.循环队列需事先固定长度,有个数限制和浪费空间的问题;
3.链队列需要指针域,产生结构性开销;