數據結構系列文章 |
---|
數據結構圖文解析之:數組、單鏈表、雙鏈表介紹及C++模板實現 |
數據結構圖文解析之:棧的簡介及C++模板實現 |
數據結構圖文解析之:隊列詳解與C++模板實現 |
數據結構圖文解析之:樹的簡介及二叉排序樹C++模板實現. |
數據結構圖文解析之:AVL樹詳解及C++模板實現 |
數據結構圖文解析之:二叉堆詳解及C++模板實現 |
數據結構圖文解析之:哈夫曼樹與哈夫曼編碼詳解及C++模板實現 |
隊列(Queue)與棧同樣,是一種線性存儲結構,它具備以下特色:html
隊列的相關概念:node
例如咱們有一個存儲整型元素的隊列,咱們依次入隊:{1,2,3}
git
添加元素時,元素只能從隊尾一端進入隊列,也便是2只能跟在1後面,3只能跟在2後面。
若是隊列中的元素要出隊:
github
元素只能從隊首出隊列,出隊列的順序爲:一、二、3,與入隊時的順序一致,這就是所謂的「先進先出」。數組
隊列一般提供的操做:數據結構
隊列與棧同樣是一種線性結構,所以以常見的線性表如數組、鏈表做爲底層的數據結構。
本文中,咱們以數組、鏈表爲底層數據結構構建隊列。oop
以數組做爲底層數據結構時,通常講隊列實現爲循環隊列。這是由於隊列在順序存儲上的不足:每次從數組頭部刪除元素(出隊)後,須要將頭部之後的全部元素往前移動一個位置,這是一個時間複雜度爲O(n)的操做:
測試
可能有人說,把隊首標誌日後移動不就不用移動元素了嗎?的確,但那樣會形成數組空間的「流失」。
咱們但願隊列的插入與刪除操做都是O(1)的時間複雜度,同時不會形成數組空間的浪費,咱們應該使用循環隊列。
所謂的循環隊列,能夠把數組看出一個首尾相連的圓環,刪除元素時將隊首標誌日後移動,添加元素時若數組尾部已經沒有空間,則考慮數組頭部的空間是否空閒,若是是,則在數組頭部進行插入。
編碼
那麼咱們如何判斷隊列是空隊列仍是已滿呢?指針
template <typename T> class LoopQueue { public: LoopQueue(int c = 10); ~LoopQueue(); public: bool isEmpty(); //隊列的判空 int size(); //隊列的大小 bool push(T t); //入隊列 bool pop(); //出隊列 T front(); //隊首元素 private: int capacity; int begin; int end; T* queue; };
隊列的操做很是簡單,這裏再也不多說
template<typename T> LoopQueue<T>::LoopQueue(int c = 10) : capacity(c), begin(0), end(0), queue(nullptr) { queue = new T[capacity]; }; template<typename T> LoopQueue<T>::~LoopQueue() { delete[]queue; } template <typename T> bool LoopQueue<T>::isEmpty() { if (begin == end) return true; return false; }; template<typename T> int LoopQueue<T>::size() { return (end-begin+capacity)%capacity; //計算隊列長度 }; template<typename T> bool LoopQueue<T>::push(T t) { if (end + 1 % capacity == begin) //判斷隊列是否已滿 { return false; } queue[end] = t; end = (end + 1) % capacity; return true; }; template <typename T> bool LoopQueue<T>::pop() { if (end == begin) //判斷隊列是否爲空 { return false; } begin = (begin + 1) % capacity; return true; }; template <typename T> T LoopQueue<T>::front() { if (end == begin) { return false; } return queue[begin]; };
int main() { LoopQueue<string> queue(6); queue.push("one"); queue.push("two"); queue.push("three"); queue.push("four"); queue.push("five"); cout << "隊列長度" << queue.size() << endl; while (!queue.isEmpty()) { cout << queue.front() << endl; queue.pop(); } getchar(); return 0; }
測試結果:
隊列長度5 one two three four five
鏈隊列是基於鏈表實現的隊列,它不存在數組的O(n)的元素移動問題或空間浪費問題。咱們所要肯定的就是鏈表哪頭作隊首,哪頭作隊尾。
顯然咱們應該以鏈表頭部爲隊首,鏈表尾部爲隊尾。存儲一個指向隊尾的指針,方便從鏈表尾插入元素;使用帶頭節點的鏈表,方便從鏈表頭刪除元素。
template<typename T> struct Node { Node(T t) :value(t), next(nullptr){} Node() = default; T value; Node<T> * next; };
鏈隊列提供的接口與循環隊列一致
template<typename T> class LinkQueue { public: LinkQueue(); ~LinkQueue(); bool isEmpty(); int size(); bool pop(); void push(T t); T front(); private: Node<T>* phead; Node<T>* pend; int count; };
template<typename T> LinkQueue<T>::LinkQueue() :phead(nullptr),pend(nullptr),count(0) { phead = new Node<T>(); pend = phead; count = 0; }; template <typename T> LinkQueue<T>::~LinkQueue() { while (phead->next != nullptr) { Node<T> * pnode = phead; phead = phead->next; } }; template <typename T> bool LinkQueue<T>:: isEmpty() { return count==0; }; template <typename T> int LinkQueue<T>::size() { return count; }; //在隊尾插入 template <typename T> void LinkQueue<T>::push(T t) { Node<T>* pnode = new Node<T>(t); pend->next = pnode; pend = pnode; count++; }; //在隊首彈出 template <typename T> bool LinkQueue<T>::pop() { if (count == 0) return false; Node<T>* pnode = phead->next; phead->next = phead->next->next; delete pnode; count--; return true; }; //獲取隊首元素 template<typename T> T LinkQueue<T>::front() { return phead->next->value; };
int _tmain(int argc, _TCHAR* argv[]) { LinkQueue<string> lqueue; lqueue.push("one"); lqueue.push("two"); lqueue.push("three"); lqueue.push("four"); lqueue.push("five"); cout << "隊列的大小" << lqueue.size() << endl; while (!lqueue.isEmpty()) { cout << lqueue.front() << endl; lqueue.pop(); } getchar(); return 0; }
運行結果:
隊列的大小5 one two three four five
循環隊列:https://github.com/huanzheWu/Data-Structure/blob/master/LoopQueue/LoopQueue/LoopQueue.h
鏈隊列:https://github.com/huanzheWu/Data-Structure/blob/master/LinkQueue/LinkQueue/LinkQueue.h
原創文章,轉載請註明出處:http://www.cnblogs.com/QG-whz/p/5171123.html#_label3_0