队列类似于人员排队。首先加入列队的人最先得到服务,并第一个离队,队列项在队尾(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 !"); } }