队列类似于人员排队。首先加入列队的人最先得到服务,并第一个离队,队列项在队尾(back或rear)加入,从对头(front)离队。队列的操作只发生在两端,这使得队列具有先进后出(first-in first-out简写为FIFO)的特性,相对而言,可认为栈只有一端。因为所有的操作都在栈顶执行。这使得栈具有后进先出的特性。
以下是对的几个实现:
1、queue的异常处理类:
#ifndef QUEUE_EXCEPTION_H_
#define QUEUE_EXCEPTION_H_
#include<stdexcept>
#include<string>
using namespace std;
class queueException:public logic_error
{
public:
queueException(const string &message="")
:logic_error(message.c_str())
{}
};
#endif
2、基于指针的队列的实现:
#ifndef QUEUE_POINTER_H_
#define QUEUE_POINTER_H_
#include<string>
#include"queue_exception.h"
template<class T>
class Queue
{
public:
//constructor and destructor
Queue();
Queue(const Queue &aqueue);
~Queue();
//operation functions
bool isEmpty()const;
//Detemines whether a queue is empty
//precondition :None
//postcondition :returns true if the queue is
//empty otherwise returns false
void enqueue(T newitem)throw(queueException);
//insert an item at the back of the queue
//precondition :newitem is the item to be inserted
//postcondition :if the insertion was successfull
//newitem is at the back of the queue
//Exception :throw queueException if newitem cannot
//be placed on the queue
void dequeue()throw(queueException);
//delete an item at the first of the queue
//precondition:none
//postcondition :if the queue is not empty, the item
//that was added to the queue earlist is delete
//exception :throws queueexception if the queue if
//empty
void dequeue(T & queueFront)throw(queueException);
//retrieve and delete the front of a queue
//precondition :none
//postcondition :if the queue is not empty
//queueFront contains the items that was
//added first and the is deleted
//exception:throw queueexception if the queue is empty
void getFront(T &queueFront)const throw(queueException);
//retrieve the item at the front of a queue
//precondition :none
//postcondition :if the queue is not empty
//queufront contains the item that was added to the queue
//earlist Exception:throw queueexception if the queue
//is empty;
private:
//the queue is implemented as a linked list
//with one external pointer to the front and
//a second pointer to the back of the queue.
struct Node
{
T items;
Node *next;
};
Node *frontPtr;
Node *backPtr;
};
#endif
#include"queue_pointer.h"
#include<cstddef>
#include<cassert>
template<class T>
Queue<T>::Queue()
{
}
template<class T>
Queue<T>::Queue(const Queue &aqueue)
{
if(aqueue.frontPtr==NULL)
frontPtr=backPtr=NULL;
else
{
Node *newPtr= new Node;
assert(newPtr!=NULL);
Node *originPtr=aqueue.frontPtr;
newPtr->items=originPtr->item;
newPtr->next=NULL;
frontPtr=newPtr;
originPtr=originPtr->next;
while(originPtr!=aqueue.backPtr)
{
newPtr->next=new Node;
assert(newPtr!=NULL);
newPtr=newPtr->next;
newPtr->items=originPtr->items;
newPtr->next=NULL;
originPtr=originPtr->next;
}
backPtr=new Node;
assert(backPtr!=NULL);
backPtr->items=originPtr->items;
backPtr->next=NULL;
}
}
template<class T>
Queue<T>::~Queue()
{
while(frontPtr!=NULL)
dequeue();
assert((frontPtr==NULL)&&(backPtr==NULL));
}
template<class T>
bool Queue<T>::isEmpty()const
{
return backPtr==NULL;
}
template<class T>
void Queue<T>::enqueue(T newitem)throw(queueException)
{
Node *newPtr=new Node;
if(newPtr==NULL)
throw queueException("queueException :insert new item faild !");
else{
newPtr->items=newitem;
newPtr->next=NULL;
backPtr->next=newPtr;
backPtr=newPtr;
}
}
template<class T>
void Queue<T>::dequeue()throw(queueException)
{
if(isEmpty())
throw queueException("queueException :delete the front item failed !");
else
{
Node *temp=frontPtr;
frontPtr=frontPtr->next;
temp->next=NULL;
delete temp;
}
}
template<class T>
void Queue<T>::dequeue(T &queueFront)throw(queueException)
{
if(isEmpty())
throw queueException("queueException :delete the front items failed !");
else
{
Node *temp=frontPtr;
frontPtr=frontPtr->next;
queueFront=temp->items;
temp->next=NULL;
delete temp;
}
}
template<class T>
void Queue<T>::getFront(T &queueFront)const throw(queueException)
{
if(isEmpty())
throw queueException("queueException :get front items failed !");
else
{
queueFront=frontPtr->items;
}
}
3、基于数组的队列的实现:
将数组看作为一个环形空间,通过在数组中顺时针移动front 和back 前移队列索引front(删除数据项)和back(插入数据项)。当front或back前移超过MAX-QUEUE-1 时,将返回0,从而消除了前面的实现中的右移的问题,因为循环数组不存在终点。在这种方案中唯一的困难是检测对空和队满的条件,似乎将“front 比back超前一个空间”作为对空的条件,这似乎说明:当队列变空时,front将超前back。只不过这个条件也可能指示一个队列已满。为此这里用了三种方法已标记队列的状态。
为初始化队列,将front设置为0,将back设置为MAX-QUEUE-1,在增加back和front时使用模运算(back=(back+1)%MAX-QUEUE),即可取得循环队列的返回效果。
1)设置一个int 成员变量count ,用于指示队列的项数。
#ifndef QUEUE_ARRAY1_H_
#define QUEUE_ARRAY1_H_
#include"queue_exception.h"
const int MAX=20;
template<class T>
class Queue
{
public:
//constructor
Queue();
//operation functions
bool isEmpty()const;
//detemines whether the queue is empty
void enqueue(T newitem)throw(queueException);
//insert an item in the back of the queue if the
//queue is not full
void dequeue()throw(queueException);
//delete an item in the front of the queue if
//queue is not empty
void dequeue(T &queueFront)throw(queueException);
//delete an item in the front of the queue if the
//queue is not empty and queueFront contains the value
//that was being delete
void getFront(T &queueFront)const throw(queueException);
//retrieve the queue and queueFront contains the
//value of the front items;
private:
T items[MAX];
int size;
int front;
int back;
};
#endif
#include"queue_array1.h"
template<class T>
Queue<T>::Queue()
{
size=0;
front=0;
back=MAX-1;
}
template<class T>
bool Queue<T>::isEmpty()const
{
return size==0;
}
template<class T>
void Queue<T>::enqueue(T newitem)throw(queueException)
{
if(size==MAX)
throw queueException("queueException :insert new itesm failed !");
else{
back=(back+1)%MAX;
items[back]=newitem;
size++;
}
}
template<class T>
void Queue<T>::dequeue()throw(queueException)
{
if(isEmpty())
throw queueException("queueException :delete the froont item failed !");
else
{
front=(front+1)%MAX;
size--;
}
}
template<class T>
void Queue<T>::dequeue(T &queueFront)throw(queueException)
{
if(isEmpty())
throw queueException("queueException :delete the front item failed !");
else
{
queueFront=items[front];
front=(front+1)%MAX;
size--;
}
}
template<class T>
void Queue<T>::getFront(T &queueFront)const throw(queueException)
{
if(isEmpty())
throw queueException("queueException :get the front item failed !");
else
{
queueFront=items[front];
}
}
2)设置一个bool 类型的变量isFull,当未满时为false,否则为true
#ifndef QUEUE_ARRAY2_H_
#define QUEUE_ARRAY2_H_
#include"queue_exception.h"
const int MAX=20;
template<class T>
class Queue
{
public:
Queue();
bool isEmpty()const;
void enqueue(T newitem)throw(queueException);
void dequeue()throw(queueException);
void dequeue(T &queueFront)throw(queueException);
void getFront(T &queueFront)const throw(queueException);
private:
T items[MAX];
int back;
int front;
bool isFull;
};
#endif
#include"queue_array2.h"
template<class T>
Queue<T>::Queue()
{
isFull=false;
front=0;
back=MAX-1;
}
template<class T>
bool Queue<T>::isEmpty()const
{
return ((front==(back+1)%MAX)&&!isFull);
}
template<class T>
void Queue<T>::enqueue(T newitem)throw(queueException)
{
if(isFull)
throw queueException("insert new item in the queue failed !");
else
{
back=(back+1)%MAX;
items[back]=newitem;
if(front==(back+1)%MAX)
isFull=true;
}
}
template<class T>
void Queue<T>::dequeue( )throw(queueException)
{
if((front==(back+1)%MAX)&&!isFull)
throw queueException("delete item in the queue failed !");
else
{
if(isFull)
isFull=false;
front=(front+1)%MAX;
}
}
template<class T>
void Queue<T>::dequeue(T &queueFront)throw(queueException)
{
if((front==(back+1)%MAX)&&!isFull)
throw queueException("delete item in the queue failed !");
else
{
if(isFull)
isFull=false;
queueFront=items[front];
front=(front+1)%MAX;
}
}
template<class T>
void Queue<T>::getFront(T & queueFront)const throw(queueException)
{
if((front==(back+1)%MAX)&&!isFull)
throw queueException("get front item failed !");
else
{
queueFront=items[front];
}
}
3)为数组声明MAX-QUEUE+1个位置,但只使用其中的MAX-QUEUE个位置,剩下的一个数组位置,使front成为对头之前位置的索引。
#ifndef QUEUE_ARRAY3_H_
#define QUEUE_ARRAY3_H_
#include"queue_exception.h"
const int MAX=21;
template<class T>
class Queue
{
public:
Queue();
bool isEmpty()const;
void enqueue(T newitem)throw(queueException);
void dequeue()throw(queueException);
void dequeue(T &queueFront)throw(queueException);
void getFront(T &queueFront)const throw(queueException);
private:
T items[MAX];
int front;
int back;
};
#endif
#include"queue_array3.h"
template<class T>
Queue<T>::Queue()
{
front=0;
back=MAX-1;
}
template<class T>
bool Queue<T>::isEmpty()const
{
return front==((back+1)%MAX);
}
template<class T>
void Queue<T>::enqueue(T newitem)throw(queueException)
{
if(front==back)
throw queueException("queueException :insert new item failed !");
else
{
back=(back+1)%MAX;
items[back]=newitem;
}
}
template<class T>
void Queue<T>::dequeue( )throw(queueException)
{
if(front==(back+1)%MAX)
throw queueException("queueException :delete the item failed !");
else
{
front=(front+1)%MAX;
}
}
template<class T>
void Queue<T>::dequeue(T &queueFront)throw(queueException)
{
if(front==(back+1)%MAX)
throw queueException("queueException :delete the item failed !");
else
{
front=(front+1)%MAX;
queueFront=items[(front+1)%MAX];
}
}
template<class T>
void Queue<T>::getFront(T &queueFront)const throw(queueException)
{
if(front==(back+1)%MAX)
throw queueException("queueException :get front item failed!");
else
{
queueFront=items[(front+1)%MAX];
}
}
这个实现没有维护计数器和标志的开销,但运行的时间更少,对于标准数据类型,该实现所需的空间与需要维护计算器或标志的实现相同,但对于比较复杂的数据,在额外数组位置上浪费的内存会非常大。
3、基于ADT的队列的实现:
#ifndef QUEUE_ADT_H_
#define QUEUE_ADT_H_
#include<list>
#include"queue_exception.h"
using namespace std;
template<class T>
class Queue
{
public:
Queue();
bool isEmpty()const;
void enqueue(T newitem)throw(queueException);
void dequeue()throw(queueException);
void dequeue(T &queueFront)throw(queueException);
void getFront(T &queueFront)const throw(queueException);
private:
list<T> alist;
};
#endif
#include"queue_adt.h"
template<class T>
Queue<T>::Queue()
{
}
template<class T>
bool Queue<T>::isEmpty()const
{
return (alist.empty());
}
template<class T>
void Queue<T>::enqueue(T newitem)throw(queueException)
{
try{
alist.insert(alist.size()+1,newitem);
}
catch(...)
{
throw queueException("queueException :insert new item failed !");
}
}
template<class T>
void Queue<T>::dequeue()throw(queueException)
{
try{
alist.remove(1);
}catch(...)
{
throw queueException("queueException :delete the front item failed !");
}
}
template<class T>
void Queue<T>::dequeue(T &queueFront) throw(queueException)
{
try{
queueFront=alist.retrieve(1);
alist.remove(1);
}catch(...)
{
throw queueException("queueException :delete the item failed !");
}
}
template<class T>
void Queue<T>::getFront(T &queueFront)const throw(queueException)
{
try{
queueFront=alist.retrieve(1);
}catch(...)
{
throw queueException("queueException : get the front item failed !");
}
}