为了充分的利用数组空间,克服上溢,可将数组空间想象成为一个环形空间,称这种环状数组表示的队列为循环队列。在这种循环队列中进行入队、出队运算时,头尾指针仍然要加1,只不过当头尾指针指向数组上界(maxsize-1)时,其加1的运算结果是指向数组的下界0,可以用i=(i+1)%maxsize来更新
template<class T> class cirqueue
{public:
cirqueue(int size)
{
if(size>0)
{
maxsize=size;
queue=new T[size];
front=0;
rear=0;
}
}
~cirqueue()
{
delete[]queue;
}
bool queueempty(){ return rear==front;}
bool queuefull(){ return ((rear+1)%maxsize==front);}
T getfront();
void enqueue(T x);
void dequeue(T &x);
private:
int front,rear;
T *queue;
int maxsize;
};
template<class T>void cirqueue<T>::enqueue(T x)
{
if(queuefull())
{
cout<<"队列已满"<<endl;
return;}
else{ queue[rear]=x;
rear=(rear+1)%maxsize;}
}
template<class T>void cirqueue<T>::dequeue(T &x)
{
if(queueempty()){
cout<<"队列为空"<<endl;
return;}
else
{
x=queue[front];
front=(front+1)%maxsize;
}
}
template<class T> T cirqueue<T>::getfront()
{
if(queueempty())
{
cout<<"队列为空"<<endl;
return -1;
}
else
return queue[front];
}
循环队列应用例子:设q是一个有11个元素的顺序循环队列,初始状态q.front=q,q.rear=0,写出做下列操作后的头指针和尾指针的变化情况,若不能入队,请指出其元素,并说明理由。
1.d,e,b,g,h入队
2.d,e出队
3.i,j,k,l,m入队
4.b出队
5.n,o,p,q,r入队
#include<iostream>
#include"queue.h"
using namespace std;
void main()
{
char ch;
cirqueue<char>q(11);
q.enqueue('d');
q.enqueue('e');
q.enqueue('b');
q.enqueue('g');
q.enqueue('h');
q.dequeue(ch);
cout<<ch<<" ";
q.dequeue(ch);
cout<<ch<<" ";
for(int i='i';i<='m';i++)
q.enqueue(i);
q.dequeue(ch);
cout<<ch<<" "<<"出队"<<endl;
for(i='n';i<='r';i++)
q.enqueue(i);
}
队列的链式存储结构简称为链队列,它是一种限制在表头删除和表尾插入的单链表。显然,仅有单链表的头指针是不便在表尾做插入操作的。为此再增加一个尾指针,使其指向链表上的最后一个结点。于是,一个链队列就由一个头指针和一个尾指针唯一确定。同顺序队列定义类似,也将队列的两个指针封装在一起
template<class T> class Linkqueue;
template<class T>class queuenode
{
public:
friend class Linkqueue<T>;
private:
T data;
queuenode<T>*next;
};
template<class T>class Linkqueue
{
public:
Linkqueue();
~Linkqueue();
bool linkempty(){ return front==rear;}
void enqueue(T x);
void dequeue(T &x);
T getfrot();
private:
queuenode<T>*front,*rear;
};
template<class T> Linkqueue::Linkqueue()
{ front=new queuenode<T>;
rear=front;
front->next=NULL;}
template<class T> Linkqueue::~Linkqueue()
{
queuenode<T>*p=front;
while(front){
p=p->next;
delete p;
front=p;
}
}
template<class T> void Linkqueue::enqueue(T x)
{
queuenode<T>*s;
s->data=x;
s->next=NULL;
rear->next=s;
rear=s;
}
template<class T> void Linkqueue::dequeue(T &x)
{
if(queueempty())
{
cout<<"队列为空"<<endl;
return;
}
else
{
x=front->data;
p=front;
front=front->next;
delete p;
}
}
循环链队列,只设置一个尾指针
template<class T>class linkqueue;
template<class T>class queuenode
{
public:
friend class linkqueue<T>;
private:
T data;
queuenode<T>*next;
};
template<class T>class linkqueue
{
public:
linkqueue();
~linkqueue();
bool queueempty(){ return rear->next==rear;}
void enqueue(T x);
void dequeue(T &x);
private:
queuenode<T>*rear;/*只设置一个尾指针*/
};
template<class T> void linkqueue<T>::enqueue(T x)
{
queuenode<T>*s;
s=new queuenode<T>;
s->data=x;
s->next=rear->next;
rear->next=s;
rear=s;
}
/*将原头结点删除,将队头结点作为新的头结点*/
template<class T> void linkqueue<T>::dequeue(T &x)
{
queuenode<T>*s,*p;
if(queueempty()){
cout<<"队列为空"<<endl;
return;
}
s=rear->next;
rear->next=s->next;
p=s->next;
x=p->data;
delete s;
}
template<class T>linkqueue<T>::linkqueue()
{
rear=new queuenode<T>;
rear->next=rear;
}
循环列队链的测试函数
#include<iostream>
#include"xqueue.h"
using namespace std;
int main()
{
linkqueue<int>q;
int x;
for(int i=1;i<=6;i++)
q.enqueue(i);
while(!q.queueempty()){
q.dequeue(x);
cout<<x<<" ";
}
return 0;
}