標籤:元素
用兩個棧實現一個隊列,並實現兩個函數appendTail和deleteHead,分別完成在隊列尾部插入結點和在隊列頭部刪除結點的功能。
棧的特點是“先進後出,後進先出”,而隊列的特點是“先進先出,後進後出”,因此可以想到只用一個棧是無法完成的,所以會需要兩個棧,先將輸入的資料都依次放入一個棧stack1中,但是先進去的資料會被壓在棧底,而棧底的資料是需要最先被取出的,可畫圖如下:
650) this.width=650;" src="http://s1.51cto.com/wyfs02/M02/7F/7C/wKioL1cggEKBVpN4AAAFntGXnsQ949.png" title="圖1.png" alt="wKioL1cggEKBVpN4AAAFntGXnsQ949.png" />
當要完成在隊列頭部刪除結點這就要用到另外一個棧stack2了,可以將第一個棧stack1的棧頂元素依次取出放進另外的棧stack2中,這樣stack1中的棧底元素就變成了stack2中的棧頂元素,當需要刪除隊列頭部結點的時候就可以pop出stack2的棧頂元素;
而需要在隊列尾部插入結點就往stack1中壓入資料:
650) this.width=650;" src="http://s4.51cto.com/wyfs02/M02/7F/7F/wKiom1cggVGStCH0AAAEaEAfJDY100.png" title="圖2.png" alt="wKiom1cggVGStCH0AAAEaEAfJDY100.png" />
也就是相當於,當stack2不為空白的時候,要刪除隊列頭部的結點就從stack2的棧頂中取出資料,如果stack2為空白的時候就將stack1中的資料全部都從棧頂取出依次放入stack2中,然後再取出stack2的棧頂元素;而要在隊列尾部插入結點的時候就直接往stack1裡面push資料,這並不影響刪除隊列首部的結點,因為每次push資料都往stack1裡面放,而當stack2不為空白的時候從stack2中pop資料,二者並不影響;
程式如下:
#include <iostream>#include <vector>using namespace std;template <class T>class Queue{private: vector<T> _stack1; //定義隊列的成員變數直接使用庫類vector vector<T> _stack2; public: Queue() //直接用類的預設建構函式,這裡會自動調用庫vector中的建構函式建立兩個棧 {} //當需要向隊列尾部放資料的時候,直接在棧1中push資料就可以了 void appendTail(T data) { _stack1.push_back(data); } //當要刪除隊列頭部的資料的時候 void deleteHead() { //先要判斷棧2中是否有資料,如果有就直接取出棧頂的元素,此時就為隊首的資料 if(!_stack2.empty()) { _stack2.pop_back(); } else//若棧2為空白,則需要將棧1中的資料調換到棧2中,以保證先進棧1的資料放在棧2的頂部 { while(!_stack1.empty()) { _stack2.push_back(_stack1.back()); _stack1.pop_back(); } if(!_stack2.empty()) _stack2.pop_back(); else { cout<<"the queue is empty..."<<endl; return; } } cout<<"the new head is "<<_stack2.back()<<endl; } //為了觀察方便,這裡定義一個列印佇列的函數,這個函數其實也就是在完成兩個棧實現隊列的過程 void print_queue() { //這裡要注意的是不能直接使用對象的成員變數stack1和stack2,因為這樣會更改對象的資料,而 //我們只是需要列印資料並不希望更改它,因此可以使用vector庫中的拷貝建構函式再構造出 //兩個臨時棧 vector<T> tmp1(_stack1); vector<T> tmp2(_stack2); cout<<"head "; if(tmp2.empty())//當棧2為空白的時候需要將棧1的資料挪到棧2再取出 { while(!tmp1.empty()) { tmp2.push_back(tmp1.back()); tmp1.pop_back(); } while(!tmp2.empty()) { cout<<tmp2.back()<<" "; tmp2.pop_back(); } } else { //當棧2不為空白的時候先取出棧2的資料,然後再將棧1的資料放入棧2再取出 while(!tmp2.empty()) { cout<<tmp2.back()<<" "; tmp2.pop_back(); if(tmp2.empty()) { while(!tmp1.empty()) { tmp2.push_back(tmp1.back()); tmp1.pop_back(); } } } } cout<<"tail"<<endl; }};int main(){ Queue<char> queue; queue.appendTail(‘a‘); queue.appendTail(‘b‘); queue.appendTail(‘c‘); queue.appendTail(‘d‘); queue.appendTail(‘e‘); queue.print_queue(); queue.deleteHead(); queue.deleteHead(); queue.print_queue(); queue.appendTail(‘f‘); queue.appendTail(‘g‘); queue.appendTail(‘h‘); queue.print_queue(); return 0;}
因為上面的隊類是模板類,因此實現了代碼複用,隊中的資料可以為任意類型;
運行程式:
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/7F/83/wKiom1chTsTSoHZiAAAsoJzIP0w367.png" title="隊列ret.png" alt="wKiom1chTsTSoHZiAAAsoJzIP0w367.png" />
《完》
本文出自 “敲完代碼好睡覺zzz” 部落格,請務必保留此出處http://2627lounuo.blog.51cto.com/10696599/1768440
用兩個棧實現一個隊列——7