一、介绍
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。
二、队列的实现方法
1、队列的数组实现
1.在实例化队列时确定数组大小并初始化数组。
2.队列功能:
① 插入元素(元素在队尾入队)push(int num)
② 删除元素(在队头元素出队)pop()
③ 查看队头元素(只查看,不删除)front()
④ 判空 isEmpty()
⑤ 判满 isFull()
⑥ 查看队列长度 length()
⑦ 清空队列 clear()
3.代码实现
(1)定长数组实现
#include <iostream>
#include <string>
using namespace std;
class Myqueue
{
private:
int head,tail;//队头指针,对尾指针
int count;//记录队列元素数量
int size;//队列容量(数组初始化大小)
int* data;//数组
public:
Myqueue(int capacity);
~Myqueue();
void push(int num);
void front();
void pop();
bool isEmpty();
bool isFull();
int length();
};
Myqueue::Myqueue(int capacity)
{
head=0,tail=0;
count=0;
size=capacity;
data=new int[capacity];
}
Myqueue::~Myqueue()
{
delete []data;
}
void Myqueue::push(int num)
{
if(isFull())
{
std::cout<<"error"<<std::endl;
return;
}
data[tail]=num;
tail=(tail+1)%size;
count++;
}
void Myqueue::front()
{
if(isEmpty())
{
std::cout<<"error"<<std::endl;
}
else
{
std::cout<<data[head]<<std::endl;
}
}
void Myqueue::pop()
{
if(isEmpty())
{
std::cout<<"error"<<std::endl;
}
else
{
std::cout<<data[head]<<std::endl;
head=(head+1)%size;
count--;
}
}
bool Myqueue::isEmpty()
{
return count==0;
}
bool Myqueue::isFull()
{
return count==size;
}
bool Myqueue::length()
{
return count;
}
void Myqueue::clear()
{
while(head!=tail)
{
pop();
}
}
(2)环形数组实现
#include <iostream>
#include <vector>
using namespace std;
/* 基于环形数组实现的队列 */
class ArrayQueue {
public:
ArrayQueue(int capacity);
~ArrayQueue();
int capacity();//获取队列容量
int size();//获取队列长度
bool isEmpty(); //队列判空
void push(int num);//元素入队
int peek(); //返回队首元素
int pop(); //元素出队
vector<int> toVector();
private:
int* nums; // 用于存储队列元素的数组
int front; // 队首指针,指向队首元素
int queSize; // 队列长度
int queCapacity; // 队列容量
};
ArrayQueue::ArrayQueue(int capacity):queCapacity(capacity),queSize(0),front(0),nums(new int[capacity])
{
}
ArrayQueue::~ArrayQueue()
{
delete[] nums;
}
/* 获取队列的容量 */
int ArrayQueue::capacity()
{
return queCapacity;
}
/* 获取队列的长度 */
int ArrayQueue::size()
{
return queSize;
}
/* 判断队列是否为空 */
bool ArrayQueue::isEmpty()
{
return queSize == 0;
}
/* 入队 */
void ArrayQueue::push(int num)
{
if (queSize == queCapacity)
{
std::cout << "队列已满" << std::endl;
return;
}
//计算队尾指针,指向队尾索引+1
//这是一个环形数组,通过取余操作实现rear越过数组尾部后回到头部
int rear = (front + queSize) % queCapacity;
nums[rear] = num;
queSize++;
}
/* 访问队首元素 */
int ArrayQueue::peek()
{
if (isEmpty())
{
throw out_of_range("队列为空");
}
return nums[front];
}
/* 出队 */
int ArrayQueue::pop()
{
int num = peek();
//队首指针向后移动一位,若越过尾部,则返回到数组头部
front = (front + 1) % queCapacity;
--queSize;
return num;
}
/* 将数组转化为 Vector 并返回 */
vector<int> ArrayQueue::toVector()
{
vector<int> arr(queSize);
//仅转换有效长度范围内的列表元素
for (int i = 0, j = front; i < queSize; i++, j++)
{
arr[i] = nums[j % queCapacity];
}
return arr;
}
2、队列的链表实现
#include <iostream>
#include <vector>
using namespace std;
/* 链表节点结构体 */
struct ListNode
{
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {} // 构造函数
};
class LinkedListQueue {
private:
ListNode* front, *rear; // 头节点 front ,尾节点 rear
int queSize;
public:
LinkedListQueue();
~LinkedListQueue();
int size(); //获取队列长度
bool isEmpty(); //判断队列是否为空
void push(int num); //入队
int pop(); //出队
int peek(); //访问队首元素
vector<int> toVector(); //链表转换为vector
};
LinkedListQueue::LinkedListQueue():front(nullptr),rear(nullptr),queSize(0)
{
}
LinkedListQueue::~LinkedListQueue()
{
// 遍历链表删除节点,释放内存
while (front != nullptr)
{
ListNode* tmp = front;
front = front->next;
delete tmp;
}
}
int LinkedListQueue::size()
{
return queSize;
}
bool LinkedListQueue::isEmpty()
{
return size() == 0;
}
/*尾插法*/
void LinkedListQueue::push(int num)
{
ListNode* node = new ListNode(num);
//如果队列为空,则令头、尾节点都指向该节点
if (front == nullptr)
{
front = node;
rear = node;
}
else//队列不为空,则将该节点添加到尾节点后
{
rear->next = node;
rear = node;
}
++queSize;
}
int LinkedListQueue::peek()
{
if (size() == 0)
{
throw out_of_range("队列为空");
}
return front->val;
}
//队头出队
int LinkedListQueue::pop()
{
//获取队首元素
int num = peek();
ListNode* tmp = front;
front = front->next;
//释放内存
delete tmp;
--queSize;
return num;
}
vector<int> LinkedListQueue::toVector()
{
vector<int> nums;
ListNode* node = front;
while (node != nullptr)
{
nums.push_back(node->val);
node = node->next;
}
return nums;
}