队列
1.队列简介:
队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,不能再任意位置插入和删除。
进行插入操作的端称为队尾,进行删除操作的端称为队头。
2.使用顺序表实现队列结构:
2.1 队列类的定义:
template<typename Type>
class SequenceQueue {
public:
SequenceQueue(int size) :front(0), count(0), maxSize(size) {
elements = new Type[size];
if (elements == nullptr) {
cout << "初始化队列对象出错" << endl;
exit(1);
}
}
~SequenceQueue() {
delete[] elements;
}
//返回队列的信息的方法
bool IsEmpty();
bool IsFull();
//对队列内元素的操作
void MakeEmpty();
bool Append(const Type item);
Type Delete();
Type Get();
//基本方法
void Print();
private:
int rear;
int front;
int count;
int maxSize;
Type * elements;
};
2.2 顺序表队列的5个私有属性:
使用顺序表实现队列,下面5个属性必不可少
属性 | 功能 |
---|---|
rear | 队列的尾部位置 |
front | 队列的头部位置 |
count | 队列元素的总数 |
maxSize | 队列的最大长度 |
elements | 存储队列元素的载体,一个数组 |
2.3 顺序表队列的工作原理:
通过改变rear和front的值,改变队列的头位置和尾位置,实现队列的增删
元素从队列的尾部进入队列,从头部离开队列
1)顺序表队列删除元素
若队列如上图所示,队列元素为a3到an,a3位于队头,an位于队尾,现在调用Delete()删除一个元素,
步骤一:front的值增1,队头向右移一位
步骤二:count的值减1,队列总元素数减1
template<typename Type>
Type SequenceQueue<Type>::Delete() {
if (IsEmpty()) {
cout << "没有可删除的元素" << endl;
exit(1);
}
Type temp = elements[front];
front = front + 1;
count--;
return temp;
}
由上的分析可以看出,顺序表队列在删除队列元素时并没有将队列元素从内存中删除
2)顺序表队列添加元素
队列添加元素和删除元素的原理相同,与删除元素不同的是首先要将添加的数据存入到载体数组中,然后再右移动队尾
template<typename Type>
bool SequenceQueue<Type>::Append(const Type item) {
if (IsFull()) {
cout << "队列超载" << endl;
return false;
}
elements[rear] = item;
rear = rear + 1;
count++;
return true;
}
2.4 顺序表队列的优化:
顺序表队列的一个问题:
如上程序,rear和front的移动方式均为自增
rear = rear + 1;
front = front + 1;
如果队列需要快速读取一小部分数据并立即将这部分数据删除,在同一时间内在队列中的数据很少,即maxSize可以是一个很小的数
但是由于数据的载体是一个顺序表,不停地向一个方向移动rear和front需要一个很多的顺序表
这时可以将顺序表设计成环形的,这个环形顺序表的长度设置为保证比maxSize大,这样就可以使队列只使用一小部分内存即可完成上述工作
如果使用链表来实现队列,则环形表非常容易实现,但是顺序表则无法实现环形的,因为数组是有向无循环的,但是可以改变rear和front的自增方式间接实现目标效果
rear = (rear + 1) % maxSize;
front = (front + 1) % maxSize;
3.使用链表实现队列结构:
原理和循序表队列的原理完全相同,这里只给出实现的代码:
template<typename Type> class LinkedQueue;
template<typename Type>
class LinkedQueueNode
{
private:
friend typename LinkedQueue<Type>;
//构造函数和析构函数
LinkedQueueNode() :pnext(nullptr) {}
LinkedQueueNode(const Type item, LinkedQueueNode<Type> * next = nullptr) :data(item), pnext(next) {}
~LinkedQueueNode() {
pnext = nullptr;
}
public:
Type GetData();
private:
Type data;
LinkedQueueNode * pnext;
};
//获取链表节点中的数据
template<typename Type> Type LinkedQueueNode<Type>::GetData() {
return this->data;
}
#pragma once
#include"LinkedQueueNode.h"
template<typename Type>
class LinkedQueue {
public:
LinkedQueue(int size) :front(0), count(0), maxSize(size), head(new LinkedQueueNode<Type>()) {
LinkedQueueNode<Type> * pmove = head;
for (int i = 0; i < size; i++){
LinkedQueueNode<Type> * pnode = new LinkedQueueNode<Type>;
pmove->pnext = pnode;
pmove = pmove->pnext;
}
pmove->pnext = head->pnext;
}
~LinkedQueue() {
MakeEmpty();
delete head;
}
//返回队列的信息的方法
bool IsEmpty();
bool IsFull();
//对队列内元素的操作
void MakeEmpty();
bool Append(const Type item);
Type Delete();
Type Get();
//基本方法
void Print();
private:
int rear;
int front;
int count;
int maxSize;
LinkedQueueNode<Type> * head;
};
template<typename Type>
void LinkedQueue<Type>::MakeEmpty() {
LinkedQueueNode<Type> *pdel;
while (head->pnext != nullptr)
{
pdel = head->pnext;
head->pnext = pdel->pnext;
delete pdel;
}
}
template<typename Type>
bool LinkedQueue<Type>::IsEmpty() {
}
template<typename Type>
bool LinkedQueue<Type>::IsFull() {
}
template<typename Type>
bool LinkedQueue<Type>::Append(const Type item) {
LinkedQueueNode<Type> * pmove = head;
for (int i = 0; i <= rear; i++){
pmove = pmove->pnext;
}
pmove->data = item;
rear++;
count++;
return true;
}
template<typename Type>
Type LinkedQueue<Type>::Delete() {
front++;
count--;
return head->pnext->data;
}
template<typename Type>
Type LinkedQueue<Type>::Get() {
Type temp = 0;
return temp;
}
template<typename Type>
void LinkedQueue<Type>::Print() {
LinkedQueueNode<Type> *pmove = head->pnext;
cout << endl << "head";
for (int i = 0; i < front; i++){
pmove = pmove->pnext;
}
for (int i = front; i < rear; i++) {
cout << "->" << pmove->data;
pmove = pmove->pnext;
}
cout << "-over" << endl;
}