《劍指Offer》附加題_用兩個隊列實現一個棧_C++版


  在《劍指Offer》中,在棧和隊列習題中,作者留下來一道題目供讀者自己實現,即“用兩個隊列實現一個棧”。
  在計算機數據結構中,棧的特點是后進先出,即最后被壓入(push)棧的元素會第一個被彈出(pop);隊列的特點是先進先出,即第一個進入隊列的元素將會被第一個彈出來。雖然棧和隊列特點是針鋒相對,但是兩者卻相互聯系,可以互相轉換。
  在“用兩個隊列實現一個棧”問題中,我們用兩個隊列的壓入和彈出來模擬棧的壓入和彈出。我們通過畫圖的手段把抽象的問題形象化。
  在上圖中,我們先往棧內壓入一個元素a。由於兩個隊列現在都是空,我們可以選擇把a插入兩個隊列中的任一個。我們不妨把a插入queue1,接下來繼續網棧內壓入b,c兩個元素。我們把它們都插入queue1。這個時候 queue1包含3個元素a,b,c,其中a位於隊列的頭部,c位於隊列的尾部。
  現在我們考慮從棧內彈出一個元素。根據棧的后入先出的原則,最后被壓入棧的c應該最先被彈出。由於c位於queue1的尾部,而我們每次只能從隊列的頭部刪除元素,因此我們可以從queueu中依次刪除a、b並插入到queue2中,再從queue1中刪除c。這就相當於從棧中彈出元素c了。我們可以用同樣的方法從棧內彈出元素b。
  接下來我們考慮從棧內壓入一個元素d.此時queue1已經有了一個元素,我們就把d插入到queue1的尾部。如果我們再從棧內彈出一個元素,此時被彈出的應該是最后被壓入的d.由於d位於queue1的尾部,我們只能先從頭部刪除queue1的元素並插入到queue2,直到queue1中遇到d再直接把它刪除。
  注意:在上述思路中,兩個隊列存在全空隊列和一個空隊列的情況。所以,在程序中進入子函數第一步,要判斷兩個隊列是否同時不為空(異常),增加程序的魯棒性。另外,空棧刪除元素要報異常,即兩個隊列均為空;
  程序實時更新在Github中: https://github.com/wylloong/TinyPrograms/blob/master/Coding%20Interviews/CStacks
               https://github.com/wylloong/TinyPrograms/blob/master/Coding%20Interviews/StackwithTwoQueues
  
************************************************************
  C++程序實現: 
// 面試題9附加題:用兩個隊列實現棧
// 題目:用兩個隊列實現一個棧。棧的聲明如下,請實現它的兩個函數appendTail
// 和deleteHead,分別完成在棧尾部插入結點和在棧頭部刪除結點的功能。

#pragma once
#include<queue>
#include<exception>

using namespace std;

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

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

private:
    queue<T> queue1;
    queue<T> queue2;
};

template<typename T> CStack<T>::CStack()
{
}

template<typename T>  CStack<T>::~CStack()
{
}

// 插入元素
template<typename T> void CStack<T>::appendTail(const T& node)
{
    if (queue1.size() > 0 && queue2.size() > 0)
    {
        //異常情況
    }
    else
    {
        //插入到非空隊列,如果均為空則插入到queue2中
        if (queue1.size() == 0)
        {
            queue2.push(node);
        }
        else
        {
            queue1.push(node);
        }
    }
}

template<typename T> T CStack<T>::deleteHead()
{
    if (queue1.size() == 0 && queue2.size() == 0)
    {
        //異常情況
        throw new exception("stack is empty");
    }
    T head;
    if (queue1.size() > 0)
    {
        while (queue1.size()>1)
        {
            //queue1中的元素依次刪除,並插入到queue2中,其中queue1刪除最后一個元素
            //相當於從棧中彈出隊尾元素

            T& data = queue1.front();
            queue1.pop();
            queue2.push(data);
        }
        head = queue1.front();
        queue1.pop();
    }
    else
    {
        while (queue2.size()>1)
        {
            //queue2中的元素依次刪除,並插入到queue1中,其中queue2刪除最后一個元素
            //相當於從棧中彈出隊尾元素

            T& data = queue2.front();
            queue2.pop();
            queue1.push(data);
        }
        head = queue2.front();
        queue2.pop();
    }
    return head;
}
#include"CStacks.h"

// ====================測試代碼====================
void test(char actual, char expected)
{
    if (actual == expected)
        printf("Test passed.\n");
    else
        printf("Test failed.\n");
}

int main(int argc, char* argv[])
{
    // 后進先出
    CStack<char> stack;

    stack.appendTail('a');
    stack.appendTail('b');
    stack.appendTail('c');

    char head = stack.deleteHead();
    test(head, 'c');

    head = stack.deleteHead();
    test(head, 'b');

    stack.appendTail('d');
    head = stack.deleteHead();
    test(head, 'd');

    stack.appendTail('e');
    head = stack.deleteHead();
    test(head, 'e');

    head = stack.deleteHead();
    test(head, 'a');

    //空棧刪除,觸發異常
    //head = stack.deleteHead();

    getchar();
    return 0;
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM