出处:http://hi.baidu.com/qq0400/item/06b51ed6c780385ad63aae8f
循环队列
为充分利用向量空间,克服"假上溢"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。
(1) 循环队列的基本操作
循环队列中进行出队、入队操作时,头尾指针仍要加1,朝前移动。只不过当头尾指针指向向量上界(QueueSize-1)时,其加1操作的结果是指向向量的下界0。这种循环意义下的加1操作可以描述为:
① 方法一:
if(i+1==QueueSize) //i表示front或rear
i=0;
else
i++;
② 方法二--利用"模运算"
i=(i+1)%QueueSize;
(2) 循环队列边界条件处理
循环队列中,由于入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是"空"还是"满"。 【参见动画演示】
解决这个问题的方法至少有三种:
① 另设一布尔变量以区别队列的空和满;
② 少用一个元素的空间。约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满(注意:rear所指的单元始终为空);
③使用一个计数器记录队列中元素的总数(即队列长度)。
代码实现:
#include <iostream>
using namespace std;
template <typename T>
class SqQueue
{
public:
SqQueue(int init = 10);
bool SqQueueEmpty() const;//判断队列是否为空
void SqQueueTraverse() const;//遍历循环队列
int SqQueueLength() const;//返回队列中元素个数
bool EnSqQueue(T e);
bool DelSqQueue();
private:
int size;//允许的最大存储空间,以元素为单位
int front;//队列头指针
int rear;//队列尾指针
T *base;//存储空间基址
};
template <typename T>
SqQueue<T>::SqQueue(int init)
{
size = init;//初始大小
base = new T[size];
if(!base)exit(1);//存储分配失败
front = rear = 0;//空栈中元素个数
}
//返回队列Q中元素个数,即队列长度
template <typename T>
int SqQueue<T>::SqQueueLength() const
{
return ((rear-front+size)%size);
}
template <typename T>
void SqQueue<T>::SqQueueTraverse() const
{
int length = (rear-front+size)%size;
cout<<"从队尾到队首为:"<<endl;
while(length--)
{
cout<<base[front+length]<<" ";
}
cout<<endl;
}
//若当前队列不满,插在当前队列的元素之后
//插入元素e为新的队列尾元素,并返回true,否则返回false。
template <typename T>
bool SqQueue<T>::EnSqQueue(T e)
{
if((rear+1)%size==front)
{//队列满
cout<<"队列已满!"<<endl;
return false;
}
else
{
base[rear] = e;
rear = (rear+1)%size;
return true;
}
}
template <typename T>
bool SqQueue<T>::DelSqQueue()
{//队列空
if(front==rear)
{
return false;
}
front = (front+1)%size;
return true;
}
int main()
{
SqQueue<int> *sq = new SqQueue<int>;
int input;
cout<<"请输入要插入元素(Ctrl+D停止输入):"<<endl;
while(cin>>input)
{
sq->EnSqQueue(input);
}
/* sq->EnSqQueue(2);
sq->EnSqQueue(3);
sq->EnSqQueue(4);
sq->EnSqQueue(5);
sq->EnSqQueue(6);
*/
cout<<"队列长度为:"<<sq->SqQueueLength()<<endl;
sq->SqQueueTraverse();
cout<<"删除对象后"<<endl;
sq->DelSqQueue();
cout<<"队列长度为:"<<sq->SqQueueLength()<<endl;
sq->SqQueueTraverse();
return 0;
}