隊列用鏈表來表示時,須要用兩個變量來記錄隊列兩端的變化:theFront,theBack.node
根據連接方向的不一樣,鏈隊有兩種連接方式(其實就是鏈表的頭插入節點和尾插入節點,頭刪除節點和尾刪除節點)。ios
插如操做時,兩種方式都是同樣的;刪除元素的時候,從頭到尾的方式更便於操做。函數
鏈隊的初始值爲queueFront=queueBack=NULL,當且僅當隊列爲空時,queueFront=NULL測試
下面是隊列鏈表的兩種描述,對比可看出,從頭至尾連接方式在刪除操做時更加方便:this
下面的代碼的具體實現:spa
/* * 測試函數 * linkedQueue.cpp */ #include<iostream> #include"linkedqueue.h" #include"myexceptions.h" int main(void) { linkedQueue<int> q; q.push(1); cout<<"Queue back is "<<q.back()<<endl; q.push(2); cout<<"Queue back is "<<q.back()<<endl; q.push(3); cout<<"Queue back is "<<q.back()<<endl; q.push(4); cout<<"Queue back is "<<q.back()<<endl; cout<<"Queue should be 1234,front to back"<<endl; if(q.empty()) cout<<"The queue is empty"<<endl; else cout <<"The queue is not empty"<<endl; cout<<"The queue size is "<<q.size()<<endl; while(!q.empty()) { cout <<"Queue front is "<<q.front()<<endl; q.pop(); cout <<"Popped front element"<<endl; } try{q.pop();} catch(queueEmpty message) { cout <<"Last pop failed"<<endl; message.outputMessage(); } return 0; }
/* * 鏈表的節點類,定義了節點該有的基本屬性 * chainNode.h */ #ifndef CHAINNODE_H #define CHAINNODE_H template<class T> struct chainNode { T element;//節點元素 chainNode<T> *next;//指向下一個元素的指針 //所需函數 chainNode() {} //節點中元素的複製 chainNode(const T& element) { this->element = element; } //節點複製 chainNode(const T &element,chainNode<T> *next) { this->element = element; this->next = next; } }; #endif // CHAINNODE_H
/* * 隊列抽象類定義 * queue.h */ #ifndef QUEUE_H #define QUEUE_H using namespace std; template<class T> class queue { public: virtual ~queue(){} virtual bool empty() const = 0;//隊列爲空判斷 virtual int size() const = 0;//隊列元素個數 virtual T& front() = 0;//隊首引用 virtual T& back() = 0;//隊尾引用 virtual void pop() = 0;//出隊 virtual void push(const T& theElement) = 0;//入隊 }; #endif // QUEUE_H
/* *鏈隊的具體實現類 * linkedQueue.h * * */ #ifndef LINKEDQUEUE_H #define LINKEDQUEUE_H #include"queue.h" #include"myexceptions.h" #include"chainnode.h" #include<sstream> using namespace std; template<class T> class linkedQueue : public queue<T> { public: //鏈隊初始化,將隊列置空 linkedQueue(int initialCapacity = 10) { queueFront = NULL; queueSize = 0; } //析構函數,釋放隊列元素,將隊列置空 ~linkedQueue() { //跟出隊類似的操做,不過是要將隊列中的元素一個一個的釋放掉 while (queueFront != NULL) { chainNode<T>* nextNode = queueFront->next; delete queueFront; queueFront = nextNode; } } bool empty() const { return queueSize == 0; } int size() const { return queueSize; } //返回隊首元素 T& front() { if(queueSize == 0) throw queueEmpty(); return queueFront->element; } //返回隊尾元素 T& back() { if(queueSize == 0) throw queueEmpty(); return queueBack->element; } //出隊操做 void pop() { if(queueFront == NULL) throw queueEmpty(); chainNode<T>* nextNode = queueFront->next; delete queueFront; queueFront = nextNode; queueSize--; } //入隊操做 void push(const T& theElement) { chainNode<T>* newNode = new chainNode<T>(theElement,NULL); if(queueSize == 0) queueFront = newNode; else queueBack->next = newNode; queueBack = newNode;//不管隊列是否爲空,都有這一步操做 queueSize++; } private: chainNode<T> *queueFront; chainNode<T> *queueBack; int queueSize; }; #endif // LINKEDQUEUE_H
/* * 異常處理類 * myExceptions.h */ #ifndef MYEXCEPTIONS_H #define MYEXCEPTIONS_H #include<string> using namespace std; //template<class T> class queueEmpty { public: queueEmpty(string theMessage = "Invalid operation on empty queue") { message = theMessage; } void outputMessage() { cout << message <<endl; } private: string message; }; #endif // MYEXCEPTIONS_H