隊列,又稱為佇列(英文queue),與棧想反,是先進先出(FIFO, First-In-First-Out)的線性表。在具體應用中通常用鏈表或者數組來實現。隊列只允許在後端(稱為rear)進行插入操作,在前端(稱為front)進行刪除操作。
隊列的操作方式和棧類似,唯一的區別在於隊列只允許新資料在後端進行添加。
隊列的架構設計如下:
抽象隊列的實現如下:
class Queue : public virtual Container{public:virtual Object& Head () const = 0;virtual void Enqueue (Object&) = 0;virtual Object& Dequeue () = 0;};
隊列的動態數組實現方式:
class QueueAsArray : public virtual Queue{protected:Array<Object*> array;unsigned int head;unsigned int tail;public:QueueAsArray (unsigned int size);void Purge ();void Accept (Visitor& visitor) const;~QueueAsArray ();// ...Object& Head () const;void Enqueue (Object& obj);Object& Dequeue ();};QueueAsArray::QueueAsArray( unsigned int size ):array (size),head (0),tail (size - 1U){count=0;}void QueueAsArray::Purge(){if (IsOwner ()){for (unsigned int i = 0; i < count; ++i){delete array [head];if (++head == array.Length ()){head = 0;}}}count = 0;}QueueAsArray::~QueueAsArray(){Purge ();}Object& QueueAsArray::Head() const{if (count == 0)throw domain_error ("queue is empty");return *array [head];}void QueueAsArray::Enqueue( Object& obj ){if (count == array.Length ())throw domain_error ("queue is full");if (++tail == array.Length ())tail = 0;array [tail] = &obj;++count;}Object& QueueAsArray::Dequeue(){if (count == 0)throw domain_error ("queue is empty");Object& result = *array [head];if (++head == array.Length ())head = 0;--count;return result;}void QueueAsArray::Accept( Visitor& visitor ) const{for (unsigned int i = 0;i < count && !visitor.IsDone (); ++i){visitor.Visit (*array [i]);}}
隊列的迭代器跟棧是差不多的,我們這裡就不實現了,再來看鏈表實現:
class QueueAsLinkedList : public virtual Queue{protected:LinkedList<Object*> list;class Iter;public:QueueAsLinkedList ();void Purge ();void Accept (Visitor& visitor) const;~QueueAsLinkedList ();// ...Object& Head () const;void Enqueue (Object& obj);Object& Dequeue ();Iterator& NewIterator() const;friend class Iter;};class QueueAsLinkedList::Iter : public Iterator{QueueAsLinkedList const& queue;ListElement<Object*> const* position;public:Iter (QueueAsLinkedList const& _queue);// ...bool IsDone () const;Object& operator * () const;void operator ++ ();void Reset ();};QueueAsLinkedList::QueueAsLinkedList():list (){count=0;}void QueueAsLinkedList::Purge(){if (IsOwner ()){ListElement<Object*> const* ptr;for (ptr = list.Head (); ptr != 0; ptr = ptr->Next ())delete ptr->Datum ();}list.Purge ();count = 0;}QueueAsLinkedList::~QueueAsLinkedList(){Purge ();}Object& QueueAsLinkedList::Head() const{if (count == 0)throw domain_error ("queue is empty");return *list.First ();}void QueueAsLinkedList::Enqueue( Object& obj ){list.Append (&obj);++count;}Object& QueueAsLinkedList::Dequeue(){if (count == 0)throw domain_error ("queue is empty");Object& result = *list.First ();list.Extract (&result);--count;return result;}void QueueAsLinkedList::Accept( Visitor& visitor ) const{ListElement<Object*> const* ptr;for (ptr = list.Head ();ptr != 0 && !visitor.IsDone (); ptr = ptr->Next ()){visitor.Visit (*ptr->Datum ());}}Iterator& QueueAsLinkedList::NewIterator() const{return *new QueueAsLinkedList::Iter(*this);}QueueAsLinkedList::Iter::Iter( QueueAsLinkedList const& _queue ):queue(_queue){Reset ();}bool QueueAsLinkedList::Iter::IsDone() const{return position == 0;}Object& QueueAsLinkedList::Iter::operator*() const{//return position->Datum();if (position != 0){return *position->Datum ();}else{return NullObject::Instance ();}}void QueueAsLinkedList::Iter::operator++(){if (position != 0){position = position->Next ();}}void QueueAsLinkedList::Iter::Reset(){position = queue.list.Head();}
2 雙端隊列
雙端隊列(deque,全名double-ended queue)是一種具有隊列和棧的性質的資料結構。雙端隊列中的元素可以從兩端彈出,其限定插入和刪除操作在表的兩端進行。直接看它的實現代碼:
class Deque : public virtual Queue{public:virtual Object& Head () const = 0;virtual Object& Tail () const = 0;virtual void Enqueue (Object& object);virtual void EnqueueHead (Object& object) = 0;virtual void EnqueueTail (Object& object) = 0;virtual Object& Dequeue ();virtual Object& DequeueHead () = 0;virtual Object& DequeueTail () = 0;};void Deque::Enqueue( Object& object ){EnqueueTail (object);}Object& Deque::Dequeue(){return DequeueHead ();}class DequeAsArray : public Deque, public QueueAsArray{public:DequeAsArray (unsigned int size);Object& Head () const;Object& Tail () const;void EnqueueHead (Object& object);void EnqueueTail (Object& object);Object& DequeueHead ();Object& DequeueTail ();void Enqueue (Object& object);Object& Dequeue ();};Object& DequeAsArray::Head() const{return QueueAsArray::Head (); }Object& DequeAsArray::Tail() const{if (count == 0)throw domain_error ("deque is empty");return *array [tail];}void DequeAsArray::EnqueueHead( Object& object ){if (count == array.Length ())throw domain_error ("deque is full");if (head-- == 0)head = array.Length () - 1U;array [head] = &object;++count;}Object& DequeAsArray::DequeueTail(){if (count == 0)throw domain_error ("deque is empty");Object& result = *array [tail];if (tail-- == 0)tail = array.Length () - 1U;--count;return result;}void DequeAsArray::EnqueueTail( Object& object ){QueueAsArray::Enqueue (object);}Object& DequeAsArray::DequeueHead(){return QueueAsArray::Dequeue ();}DequeAsArray::DequeAsArray( unsigned int size):QueueAsArray(size)//重點!!這裡必須調用基類的自訂建構函式,因為基類的預設建構函式已經消失......//否則:沒有合適的預設建構函式可用{//QueueAsArray(size);count=0;}void DequeAsArray::Enqueue( Object& object ){Deque::Enqueue(object);}Object& DequeAsArray::Dequeue(){return Deque::Dequeue();}class DequeAsLinkedList : public Deque, public QueueAsLinkedList{public:DequeAsLinkedList ();// ...Object& Head () const;Object& Tail () const;void EnqueueHead (Object& object);void EnqueueTail (Object& object);Object& DequeueHead ();Object& DequeueTail ();void Enqueue (Object& object);Object& Dequeue ();};Object& DequeAsLinkedList::Head() const{return QueueAsLinkedList::Head ();}Object& DequeAsLinkedList::Tail() const{if (count == 0)throw domain_error ("deque is empty");return *list.Last ();}void DequeAsLinkedList::EnqueueHead( Object& object ){list.Prepend (&object);++count;}void DequeAsLinkedList::EnqueueTail( Object& object ){QueueAsLinkedList::Enqueue (object);}Object& DequeAsLinkedList::DequeueHead(){return QueueAsLinkedList::Dequeue ();}Object& DequeAsLinkedList::DequeueTail(){if (count == 0)throw domain_error ("deque is empty");Object& result = *list.Last ();list.Extract (&result);--count;return result;}DequeAsLinkedList::DequeAsLinkedList(){count=0;}void DequeAsLinkedList::Enqueue( Object& object ){Deque::Enqueue(object);}Object& DequeAsLinkedList::Dequeue(){return Deque::Dequeue();}