1. 程式人生 > >C++實現用兩個棧模擬一個佇列

C++實現用兩個棧模擬一個佇列

  • 問題描述

用兩個棧來實現一個佇列,佇列的宣告如下,實現其中的兩個函式,分別完成在佇列尾部插入節點和在佇列頭部刪除節點的操作。

宣告:

template <typename T> class CQueue
{
public:
    CQueue(void);
    ~CQueue(void);

    void appendTail(const T& element)
    T deleteHead();

privite:
    stack <T> stack1;
    stack <T> stack2;    
}

其中appendTail函式是佇列尾部插入節點函式,deleteHead是刪除佇列頭部節點函式。

  • 問題分析

眾所周知棧是一種先進後出的結構,而佇列是先進先出的。如果我們需要使用兩個FILO的結構實現FIFO,不妨這麼思考:

分別給兩個棧編號,叫做stack1和stack2.我們插入資料時,先將資料都按順序給stack1裡壓棧。比如我傳入的資料是1,2,3,按照 佇列來說輸出也應該是1,2,3.我們先將1,2,3壓入stack1,那麼此時stack1從棧底到棧頂分別為1,2,3.接著,我們將stack1全部出棧,並且每出一個就向stack2壓棧。完成這步操作之後,stack2中的資料從棧底到棧頂就是3,2,1了。此時對stack2進行出棧操作,順序就和佇列的完全一樣了。

那麼,如果我們現在已經將stack1中的資料全部壓棧進入stack2了,這時又插入了一個數據,該怎麼處理呢?

我們只需將新插入的資料壓入stack1,並且只要stack2非空的話,stack1就不用向stack2壓棧。這樣就保證了即使新插入資料,也不會對模擬佇列造成影響。

對於題中要求的兩個函式:首先第一個要求在佇列尾插入資料。我們經過上面的分析相信你也體會到了,其實stack1就是我們模擬佇列的隊尾。只不過“隊尾”中的節點需要出棧再壓入stack2才能用於出隊。所以具體實現只需要stack1.push(element)。

第二個問題:先判斷stack2是否空,為空的話就從stack1中拿節點壓棧。如果stack1也為空的話,佇列就是真正的空隊,無法進行pop操作了。否則,定義一個T型別的變數,記錄stack2.top()用於返回,然後stack2呼叫一次pop函式即可。

具體程式碼:

template <typename T> void CQueue <T>::appendTail(const T& element)
{
    stack1.push(element);
}

template <typename T> T CQueue<T>::deleteHead()
{
    if(stack2.size() <= 0)
    {
        while(stack1.size() > 0)
        {
            T& data = stack1.top();
            stack1.pop();
            stack2.push(data);
        }
    }

    if(stack2.size() == 0)
    {
        throw new exception("Queue is empty.");
    }

    T head = stack2.top();
    stack2.pop();
    return head;
}