定义:队列也是一种线性表。其特点是队列的插入与删除在两端进行,是一个先进先出(FIFO)的线性表。插入元素的一端叫队尾,删除元素的一端叫队首。
三种表现形式:
1、
公式1: location(i)=i
——队列第i个元素映射到数组中,即为下标为i的元素,i>=0。
2、
公式2:location(i)=location(队首元素)+i
——队列第i个元素在数组中的位置只与队首元素有关,则删除一个队首元素时不需要吧元素左移,queueFront加1就好。因此可以解决1中的问题。
3、
公式3:location(i)=(location(队首元素)+i)% arrayLength
——把数组视为一个环,则2中出现的空间利用率不高的问题可以解决。
在1,2中queueFront=queueBack=-1,在3中对数组下标求余%,故初始状态queueFront=queueBack=0,若对图3中左上角数组继续插入一个元素D,假设可以插在下标为0处,则queueFront=queueBack,不能判断此时队列是空还是满,因此应空余一个空间给queueFront标识。即在初始化的空队列中,插入的第一个元素位于队列数组下标为1的位置,而不是0。每次插入一个新元素,queueBack=(queueBack+1)% arrayLength,是考虑到循环插入数组中。
代码:
#pragma warning(disable:4996)
#include<iostream>
using namespace std;
template<typename T>
class queue
{
public:
virtual ~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; //把元素加入队尾
};
template<typename T>
class arrayQueue : public queue<T>
{
public:
arrayQueue(int initialCapacity = 10);
~arrayQueue() { delete[] que; }
bool empty() const { return queueFront == queueBack; }
int size() const;
T& front();
T& back();
void pop();
void push(const T& theElement);
private:
T* que;
int queueFront; //首元素前一位置的下标
int queueBack; //尾元素的下标
int arrayLength;
};
template<typename T> arrayQueue<T>::arrayQueue(int initialCapacity)
{
if (initialCapacity < 0)
{
cout << "队列容量必须不小于0!" << endl;
exit(-1);
}
que = new T[initialCapacity];
queueFront = queueBack = 0;
arrayLength = initialCapacity;
}
template<typename T> int arrayQueue<T>::size() const
{
if (queueBack >= queueFront)
{
return queueBack - queueFront;
}
else{
return arrayLength - queueFront - 1 + queueBack + 1;
}
}
template<typename T> T& arrayQueue<T>::front()
{
if (queueBack == queueFront)
{
cout << "队列为空,故不存在队首元素!";
exit(-1);
}
return que[queueFront+1];
}
template<typename T> T& arrayQueue<T>::back()
{
if (queueBack == queueFront)
{
cout << "队列为空,故不存在队尾元素!";
exit(-1);
}
return que[queueBack];
}
template<typename T> void arrayQueue<T>::pop()
{
if (queueBack == queueFront)
{
cout << "队列为空!";
return ;
}
queueFront = (queueFront + 1) % arrayLength;
}
template<typename T> void arrayQueue<T>::push(const T& theElement)
{
if ((queueBack + 1) % arrayLength == queueFront) //容量已满,需扩充
{
T* newArray = new T[arrayLength * 2];
//第一步,将从queueFront到arrayLength范围内的元素进行复制
copy(que + queueFront + 1, que + arrayLength, newArray+1);
//第二步,若queueBack < queueFront ,则进行剩余元素的复制
if (queueBack<queueFront)
copy(que, que + queueBack, newArray + 1 + arrayLength - queueFront - 1);
//设置新的队首和队尾,队的容量
queueFront = 0;
queueBack = arrayLength -1;
arrayLength = arrayLength * 2;
delete[] que;
que = newArray;
}
queueBack = (queueBack + 1) % arrayLength; //新的队尾标识
que[queueBack] = theElement;
}
int main(int argc, char* argv[])
{
arrayQueue<int> AQ(6);
cout << "将元素5插入队列中:" << endl;
AQ.push(5);
cout << "队首元素:" << AQ.front() << endl;
cout << "队尾元素:" << AQ.back() << endl;
cout << "队总元素:" << AQ.size() << endl;
cout << endl;
AQ.push(4);
AQ.push(3);
AQ.push(2);
AQ.push(1);
cout << "将元素4,3,2,1依次插入队列中:" << endl;
cout << "队首元素:" << AQ.front() << endl;
cout << "队尾元素:" << AQ.back() << endl;
cout << "队总元素:" << AQ.size() << endl;
cout << endl;
AQ.pop();
AQ.pop();
AQ.pop();
AQ.pop();
AQ.push(6);
AQ.push(7);
cout << "删除4个队首元素,插入2个新元素后:" << endl;
cout << "队首元素:" << AQ.front() << endl;
cout << "队尾元素:" << AQ.back() << endl;
cout << "队总元素:" << AQ.size() << endl;
cout << endl;
AQ.push(0);
cout << "继续插入元素0:" << endl;
cout << "队首元素:" << AQ.front() << endl;
cout << "队尾元素:" << AQ.back() << endl;
cout << "队总元素:" << AQ.size() << endl;
return 0;
}
运行: