一、队列
队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。我们把允许插入的一端称为队尾,允许删除的一端称为队头。队列是一种先进先出(FIFO)的线性表。
比如人们在买东西排队的时候,整个队伍可以看做一个队列,我们当然不希望有人加沙了。在服务器的应用中,也要一个队列来选择相应服务的优先级。
队列的基本操作和栈类似,有创建空队列,添加元素,删除元素,返回队列大小,返回队头和队尾元素等等。在C++标准库中,也有队列的定义。
队列也有顺序存储结构和链式存储结构,其C++实现如下:
二、队列的抽象基类
//队列的抽象类
#pragma once
#include<iostream>
using namespace std;
template<class T>
class queue
{
public:
~queue() {}
virtual bool empty() const = 0;//判断是否为空
virtual int size() const = 0;//返回队列的大小
virtual T& front() = 0;//返回头元素的引用
virtual T& back() = 0;//返回尾元素的引用
virtual void pop() = 0;//删除首元素
virtual void push(const T& theElement) = 0;//添加队列元素
virtual void output(ostream& out) const = 0;//输出
};
三、队列的数组表示
#pragma once
#include<iostream>
#include <algorithm>
#include<string>
#include<iterator>
#include"queue.h"
using namespace std;
//使用环形数组实现队列,Front指向第一个元素的前一个位置,Back指向最后一个元素
template<class T>
class arrayQueue : public queue<T>
{
public:
arrayQueue(int initialCapacity = 10);
~arrayQueue() { delete[] queue; }
bool empty() const { return theFront == theBack; }
int size() const
{
return (theBack - theFront + arrayLength) % arrayLength;
}
T& front()
{//返回首元素
if (theFront == theBack)
{
cerr << "Queue is empty";
exit(0);
}
return queue[(theFront + 1) % arrayLength];
}
T& back()
{// 返回尾元素
if (theFront == theBack)
{
cerr << "Queue is empty";
exit(0);
}
return queue[theBack];
}
void pop()
{// 弹出队列首元素
if (theFront == theBack)
{
cerr << "Queue is empty";
exit(0);
}
theFront = (theFront + 1) % arrayLength;
queue[theFront].~T(); //析构T
}
void push(const T& theElement);
void output(ostream& out) const;
private:
int theFront; // 指向队列首元素的前一个
int theBack; // 指向队列尾元素
int arrayLength; // 队里容量
T *queue; //队列指针
};
template<class T>
arrayQueue<T>::arrayQueue(int initialCapacity)
{// 构造函数
if (initialCapacity < 1)
{
cerr << "Initial Capacity Must be >0";
exit(0);
}
arrayLength = initialCapacity;
queue = new T[arrayLength];
theFront = 0;
theBack = 0;
}
template<class T>
void arrayQueue<T>::push(const T& theElement)
{//添加元素.
// 如果队列满,增加队列容量
if ((theBack + 1) % arrayLength == theFront)
{// 双倍长度
// 创建新数组
T* newQueue = new T[2 * arrayLength];
//赋值元素
int start = (theFront + 1) % arrayLength;
if (start < 2)
// 没有形成环,直接从Front到Back赋值
copy(queue + start, queue + start + arrayLength - 1, newQueue);
else
{ // 队列形成环,先从Front到数组的末尾进行复制,然后在数组开始到Back进行复制
copy(queue + start, queue + arrayLength, newQueue);
copy(queue, queue + theBack + 1, newQueue + arrayLength - start);
}
// 设置新队列的首尾位置
theFront = 2 * arrayLength - 1;
theBack = arrayLength - 2; // 队列长度 arrayLength - 1
arrayLength *= 2;
queue = newQueue;
}
// 添加元素操作
theBack = (theBack + 1) % arrayLength;
queue[theBack] = theElement;
}
//输出操作
template<class T>
void arrayQueue<T>::output(ostream& out) const
{
T* newQueue = new T[arrayLength+5];
int start = (theFront + 1) % arrayLength;
if (start < 2)//没有形成环
copy(queue + start, queue + arrayLength, newQueue);
else
{//队列形成环
copy(queue + start, queue + arrayLength, newQueue);
copy(queue, queue + theBack + 1, newQueue + arrayLength - start);
}
copy(newQueue, newQueue + size(), ostream_iterator<T>(out, " "));
}
template<class T>
ostream& operator<<(ostream& out, const arrayQueue<T>& x)
{
x.output(out);
return out;
}
测试代码:
#include<iostream>
#include"arrayQueue.h"
using namespace std;
void main()
{
arrayQueue<int> que(4);
cout << que.empty() << endl;
for (int i = 0; i < 8; i++)
{
que.push(i);
}
cout << que << endl;
cout << que.front() << " " << que.back() << endl;
que.pop();
que.pop();
cout << que << endl;
cout << que.front() << " " << que.back() << endl;
}
四、队列的链表描述
#pragma once
#include<iostream>
#include"queue.h"
using namespace std;
template<class T>
struct linkedNode
{
T element;//数据域
linkedNode<T>* next;//指针域
linkedNode(){}
linkedNode(const T& element){ this->element = element; }
linkedNode(const T& element, linkedNode<T>* next) { this->element = element; this->next = next; }
};
//队列的链表表示
template<class T>
class linkedQueue :public queue<T>
{
public:
//构造函数和析构函数
linkedQueue(int initialCapacity = 10)
{
queueFront = queueBack = NULL;
queueSize = 0;
}
~linkedQueue()
{
while (queueFront->next != NULL)
{
linkedNode<T>* nextNode = queueFront->next;//新的节点指示下一个节点
delete queueFront;//删除当前节点
queueFront = nextNode;//将下一个节点赋给当前结点
}
}
//抽象数据类型的实现
bool empty() const //判断是否为空
{
return queueSize == 0;
}
int size() const //返回队列的大小
{
return queueSize;
}
T& front() //返回头元素的引用
{
if (queueSize==0)
{
cerr << "The Queue is empty";
exit(0);
}
return queueFront->element;
}
T& back() //返回尾元素的引用
{
if (queueSize == 0)
{
cerr << "The Queue is empty";
exit(0);
}
return queueBack->element;
}
void pop();//删除首元素
void push(const T& theElement);//添加队列元素
void output(ostream& out) const ;//输出
private:
linkedNode<T>* queueFront;//指向队列首元素
linkedNode<T>* queueBack;//指向队列尾元素
int queueSize;
};
//插入操作到队尾
template<class T>
void linkedQueue<T>::push(const T& theElement)
{
linkedNode<T>* newNode = new linkedNode<T>(theElement, NULL);//分配新的空间
if (queueSize==0)
{//空队列插入到第一位
queueFront = newNode;
}
else
{//插入到尾部
queueBack->next = newNode;
}
queueBack = newNode;
queueSize++;
}
//删除队列首元素
template<class T>
void linkedQueue<T>::pop()
{
if (queueSize == 0)
{
cerr << "The Queue is empty";
exit(0);
}
linkedNode<T>* nextNode = queueFront->next;
delete queueFront;
queueFront = nextNode;
queueSize--;
}
//输出操作
template<class T>
void linkedQueue<T>::output(ostream& out) const //吧链表放入到输出流
{
for (linkedNode<T>* currentNode = queueFront; currentNode != NULL; currentNode = currentNode->next)
out << currentNode->element << " ";
}
template<class T>
ostream& operator<<(ostream& out, const linkedQueue<T>& x)
{
x.output(out);
return out;
}
测试代码:
#include<iostream>
#include"linkedQueue.h"
using namespace std;
void main()
{
linkedQueue<int> que(4);
//que.pop();
cout << que.empty() << endl;
for (int i = 0; i < 17; i++)
{
que.push(i);
}
cout << que << endl;
cout << que.front() << " " << que.back() << endl;
que.pop();
que.pop();
cout << que << endl;
cout << que.front() << " " << que.back() << endl;
}