兩個棧模擬乙個佇列

2021-09-30 13:23:16 字數 1543 閱讀 9896

畢業後進入第一家公司其中有一道面試題就是用兩個佇列模擬乙個棧,自己在面試中也喜歡出這道題。最近又看到了這個問題,做個總結吧,先談談比它略簡單一些的用兩個棧模擬乙個佇列。

一,解法

這個問題一般的人都會有想法,如果面試中遇到想不到的人直接pass應該沒什麼問題。大家都明白乙個道理,負負得正,兩次先進後出正好相當於一次先進先出。有了這個思路,幾乎就已經解出了這道題。

假設我們有兩個容量都為n的棧stack1和stack2。入隊的操作可以是這樣:檢視stack1是否已滿,未滿則直接入棧;若stack1已滿且stack2為空,則將stack1中的元素轉移到stack2中;如果發現stack1滿了並且stack2不為空,此時已經不能再繼續入棧了,否則最後插入元素到stack1中。

出隊的操作是這樣的:檢視stack2中是否有元素,若有則直接出棧;若stack2為空且stack1不為空,同樣將stack1中的元素轉移到stack2;如果兩個stack都是空的,說明整個佇列是空的,否則最後在stack2**棧。

當然,這只是其中的一種解法,主要的地方是要堅持下面的原則。stack2作為出隊的操作棧,從棧頂到棧底的元素即是按出隊順序排好的元素。若stack2中已經有元素,則不能再向stack2中新增,否則會在準備出隊的元素前面新增上其他元素。

二,效能分析與改進

根據上面的步驟可以得出,這個佇列的最大容量是2n,即兩個棧的容量和。最壞情況下,佇列的容量是什麼呢?考慮這樣乙個情況,stack1中剛有兩個元素的時候,來個乙個出隊請求,這時候stack1中的元素轉移到stack2中,然後對stack2進行一次出棧,stack1變為空棧,stack2中有乙個元素。但是,此時stack2中已經有了元素,已經不能把stack1中的元素再轉到stack2中了。所以此時再進行多次入隊直到stack1變滿,就已經不能再入隊了,這個時候的佇列容量是n+1。

看懂的人可能會想到,你傻呀,再把stack2中的元素轉回來不就可以了。是的,可以針對在stack1未滿時進行出隊操作進行改造。如果在出隊時發現stack2為空且stack1未滿,則將stack1中的元素都轉到stack2中,執行完出隊操作後再將stack2中的元素轉回到stack1中,等到stack1變滿時在轉到stack2中。這樣就會到達乙個效果,stack1滿後才會被迫將元素真正轉到stack2中,而轉移元素後,stack1又可以作為乙個空棧接收n個新元素。舉個例子,12345入隊到stack1中,現在需要出隊,則12345轉到stack2中為54321,1出隊後stack2中還剩5432,轉回到stack1中為2345。這種情況有乙個缺點,如果佇列經常在stack1未滿的時候出隊,它的效率會變低,因為原來從stack1到stack2只轉了一次,現在要來迴轉三次。

如果兩個棧的容量不一樣呢?這時候怎麼辦呢?假設兩個棧的容量分別為n1、n2。可以讓容量比較大的作為入隊的棧stack1。在入隊時如果發現stack1的元素數目已經到了n2,而且此時stack2正好為空,則將stack1中的元素全部轉到stack2中。為什麼要這樣呢,上文中提到一條原則,stack2不為空的時候是不能互相轉資料,這個時候相當於鎖定了n2的容量,所以我們選擇容量較小的棧作為出隊的操作棧stack2。

兩個棧模擬乙個佇列 兩個佇列模擬乙個棧

解題思路 插入操作在stack1中進行,刪除操作在stack2中進行,如果stack2為空,則將stack1中的所有元素轉移到stack2中。include include includeusing namespace std template class cqueue 建構函式 template ...

兩個棧模擬乙個佇列

兩個棧模擬乙個佇列,1號棧為入隊,棧頂表示隊尾 2號棧為出隊,棧頂表示隊首。入隊,直接進1號棧 出隊,先判斷2號棧是否有元素,有元素就直接彈出棧頂即隊首,如果2號棧沒有元素,則將1號棧的元素順序彈出並進2號棧。cpp view plain copy include include include u...

兩個佇列模擬乙個棧

上文給出了兩個棧模擬乙個佇列的解法,本文繼續解決兩個佇列模擬乙個棧的問題。先進先出變成先進後出,乍一想可能覺得不可能。但是這道題的前提是用兩個佇列,我們完全可以用其中乙個佇列queue1儲存好要出棧的元素,每當有新元素要入棧的時候就把他加到queue1中。怎麼讓queue1中的元素按出棧順序排列呢,...