数据结构之队列queue
C++數(shù)據(jù)結(jié)構(gòu)之隊(duì)列queue
什么是隊(duì)列
隊(duì)列的基本特征
隊(duì)列是如何工作的
隊(duì)列的實(shí)現(xiàn)
隊(duì)列的應(yīng)用
什么是隊(duì)列
與棧相反,隊(duì)列是一種先進(jìn)先出(FIFO)的線性表,只允許在表的一端插入,在另一端刪除。允許插入的一端叫隊(duì)尾,允許刪除 的一端叫隊(duì)頭。比較典型的例子有日常生活中的排隊(duì):銀行排序辦理業(yè)務(wù)、地鐵排隊(duì)上車(emmmm,這里假設(shè)所有人都遵守秩序)等,當(dāng)然還有計(jì)算機(jī)系統(tǒng)的消息隊(duì)列,操作系統(tǒng)的作業(yè)調(diào)度(這兩者都可以看做是隊(duì)列,不過(guò)是隊(duì)列的高級(jí)應(yīng)用:優(yōu)先級(jí)隊(duì)列)等
隊(duì)列的基本特征
- 先進(jìn)先出(FIFO) - 限制插入和刪除:隊(duì)尾(back)插入,隊(duì)頭(front)刪除隊(duì)列是如何工作的
如下圖所示:
front代表隊(duì)頭,back代表隊(duì)尾,初始狀態(tài),front與back指向同一位置,當(dāng)插入一個(gè)新元素a后,隊(duì)尾back向后移動(dòng)一位,隊(duì)頭front不動(dòng),指向下一個(gè)位置,當(dāng)在a的下一個(gè)位置插入元素b時(shí),隊(duì)尾back繼續(xù)向后移動(dòng)一位,直到滿隊(duì)列,此時(shí)back指向最后的位置。當(dāng)刪除一個(gè)元素時(shí),隊(duì)頭front向后移動(dòng)一位,隊(duì)尾back不動(dòng)。在這種隊(duì)列結(jié)構(gòu)下,可以通過(guò)(front == back)來(lái)判斷隊(duì)列是否為空。
隊(duì)列的實(shí)現(xiàn)
隊(duì)列的實(shí)現(xiàn)主要有兩種方式:順序表和鏈表;隊(duì)列的操作主要有:取出隊(duì)頭元素(front())、 刪除隊(duì)頭元素(pop())、隊(duì)尾插入元素(push())、是否為空(Empty())、隊(duì)列元素?cái)?shù)(size()) 、是否已滿(Full())順序表實(shí)現(xiàn)隊(duì)列
順序表的實(shí)現(xiàn)較為簡(jiǎn)單,直接使用數(shù)據(jù)存儲(chǔ)數(shù)據(jù)即可,而front和back代表數(shù)組的下標(biāo)(索引), 這樣做的缺點(diǎn)就是隊(duì)列的長(zhǎng)度固定,同時(shí)由于每次刪除元素時(shí),隊(duì)頭向后移動(dòng)一位,當(dāng)隊(duì)列中所有 元素被刪除時(shí),此時(shí)front ==back,但是,此時(shí)繼續(xù)向隊(duì)列中插入元素時(shí),就會(huì)出現(xiàn)數(shù)組越界的 情況。 如上所示,此時(shí),front與back都以指向了最后位置,無(wú)法繼續(xù)在隊(duì)列中插入數(shù),但是, front前面的空間仍舊是空的,沒(méi)有存儲(chǔ)內(nèi)容,此時(shí)如果采用動(dòng)態(tài)內(nèi)存分配無(wú)疑會(huì)浪費(fèi)內(nèi) 存空間,因此,為了能夠充分利用已分配的數(shù)組空間,可以將數(shù)組想象為一個(gè)首尾相 接的環(huán),循環(huán)存儲(chǔ)數(shù)據(jù),稱之為循環(huán)隊(duì)列。 如上,將數(shù)組想象成環(huán)狀,初始時(shí),front與back都指向起始位置,當(dāng)有元素插入或者刪除時(shí), 進(jìn)行相應(yīng)的移動(dòng),直到back的下一個(gè)位置為front時(shí),隊(duì)列為滿。由于是環(huán)狀的,因此, front與back的代表的位置應(yīng)該對(duì)隊(duì)列的長(zhǎng)度取余后,才為數(shù)組的下標(biāo)。同時(shí),為了便于判斷 隊(duì)列為滿和隊(duì)列為空,在設(shè)置隊(duì)列長(zhǎng)度時(shí),應(yīng)該為length+1,因?yàn)?span id="ozvdkddzhkzd" class="hljs-keyword">back始終指向隊(duì)尾元素的 下一個(gè)位置,所以,當(dāng)隊(duì)列滿時(shí),back應(yīng)該指向隊(duì)列長(zhǎng)度的下一個(gè)位置,從而,可以通過(guò) (back+1)%(length+1) == front判斷隊(duì)列滿,通過(guò)back==front判斷隊(duì)列為空。代碼實(shí)現(xiàn)
//頭文件定義 template <typename T> class Queue { public:Queue(int max_size);virtual ~Queue();T & Front() const;void Pop();void Push(T &element);bool Empty() const;int size() const;bool Full() const; private:int front_;int back_;int size_;int max_size_;T *contain; //隊(duì)列指針};//代碼實(shí)現(xiàn) #include "Queue.h" #include <iostream> #include <assert.h> ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// template <typename T> Queue<T>::Queue(int max_size) {front_ = back_ = 0;size_ = 0;max_size_ = max_size + 1;contain = new T[max_size_]; //比隊(duì)列長(zhǎng)度多一個(gè)元素,用于輔助存放back_以及判斷滿 }template <typename T> Queue<T>::~Queue() {delete [] contain; }template <typename T> bool Queue<T>::Empty() const {return front_ == back_; //指向同一位置 }template <typename T> T & Queue<T>::Front() const {assert(!Empty()); //斷言不為空,為空則程序直接報(bào)出異常中止return contain[front_]; }template <typename T> bool Queue<T>::Full() const {return (back_ + 1) % max_size_ == front_; //由于是環(huán)狀所以對(duì)最大長(zhǎng)度取余 }template <typename T> void Queue<T>::Pop() {front_ = (front_ + 1) % max_size_;size_--; }template <typename T> void Queue<T>::Push(T &element) {assert(!Full());contain[back_] = element;back_ = (back_ + 1) % max_size_;size_++; }template <typename T> int Queue<T>::size() const {return size_; }鏈表實(shí)現(xiàn)隊(duì)列
用鏈表來(lái)實(shí)現(xiàn)隊(duì)列更符合隊(duì)列的特征,不需要進(jìn)行循環(huán),刪除隊(duì)頭元素直接釋放隊(duì)頭元素 空間即可,插入隊(duì)尾時(shí),直接新增空間即可添加,同時(shí)隊(duì)尾指針指向隊(duì)尾元素,不再指向 下一節(jié)點(diǎn),如下圖所示。 與鏈表不同的是,鏈表有頭結(jié)點(diǎn),而隊(duì)列不需要頭結(jié)點(diǎn),空隊(duì)列時(shí),隊(duì)頭指針與隊(duì)尾指針 都指向NULL,同時(shí)此時(shí)判斷隊(duì)列滿也沒(méi)有什么意義。因而用鏈表實(shí)現(xiàn)隊(duì)列的功能有取頭 節(jié)點(diǎn)(Front())、刪除頭節(jié)點(diǎn)(Pop())、插入新元素(Push())、是否為空(Empty()) 、隊(duì)列中元素個(gè)數(shù)(size())代碼實(shí)現(xiàn)
//頭文件定義 template <typename T> //節(jié)點(diǎn) struct ListNode{T data;ListNode<T> *link; }; //鏈表類 template <typename T> class ListQueue { public:ListQueue();virtual ~ListQueue();T & front() const;void Pop();void Push(T &element);bool Empty() const;int size() const; private:int size_;ListNode<T> *front_;ListNode<T> *back_; };//cpp實(shí)現(xiàn) #include "ListQueue.h" #include <iostream> #include <assert.h>////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// template <typename T> ListQueue<T>::ListQueue() {front_ = back_ = NULL;size_ = 0; }template <typename T> ListQueue<T>::~ListQueue() {while (!Empty()) {this->Pop();} }template <typename T> bool ListQueue<T>::Empty() const {return front_ == NULL; }template <typename T> T & ListQueue<T>::front() const{assert(!Empty());return front_->data; }template <typename T> void ListQueue<T>::Pop() {assert(!Empty());ListNode<T> *temp = front_;front_ = front_->link;delete temp;size_--; }template <typename T> void ListQueue<T>::Push(T &element) {ListNode<T> *new_node= new ListNode<T>;new_node->data = element;new_node->link = NULL;if (back_ == NULL) {front_ = back_ = new_node;} else {back_->link = new_node;back_ = back_->link;}size_++; }template <typename T> int ListQueue<T>::size() const {return size_; }隊(duì)列的應(yīng)用
編程練習(xí)之隊(duì)列篇:舞伴問(wèn)題
編程練習(xí)之隊(duì)列篇:游程編碼問(wèn)題
編程練習(xí)之隊(duì)列篇:楊輝三角問(wèn)題
編程練習(xí)之隊(duì)列篇:優(yōu)先級(jí)隊(duì)列
未完待續(xù)
以上是我關(guān)于隊(duì)列的學(xué)習(xí)心得,如果有什么不對(duì)的地方,歡迎大家指出,一起交流討論
總結(jié)
以上是生活随笔為你收集整理的数据结构之队列queue的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 迅雷 linux 命令行 版本号,在Li
- 下一篇: 批处理事件查看器