棧的經典面試題之用兩個棧實現一個隊列


     拿到這種問題,我們首先應該思考這兩種結構的特性是什么,為什么會出這樣的題。其實就說明這兩者的特性是有某種聯系的,這么想的話其實很簡單,棧的最大特點就是先進后出,讓我們用兩個先進后出的棧來實現一個先進先出的隊列,那么我們把數據壓入第一個棧,此時我們很清楚它的出戰順序是與我們想要的隊列的出隊順序是相反的,如果再把這個棧里面的元素依次壓入第二個棧,此時我們想想棧2里面的元素的順序,相當於對一組數據進行了兩次倒序,此時對第二個棧進行的出棧操作的順序就相當於這組數據進入隊列的順序了。
      上面這段話是對思路的一個詳細分析,但是是比較啰嗦的,大家完全可以通過思考就能想明白而不必要看它,當然你也可以湊合瞅瞅,縷縷思路。可以看看下面的圖,假設現在入隊的元素是1,2,3,4,那么入隊之后處在隊頭的元素為1,隊尾為4,那么我們想要通過s1和s2實現這樣的隊列。
                      
  接下來才是重點所在,我們要用這兩個棧來實現一個隊列,那么需要寫出隊列中的幾個基本操作函數,如下所示:
                       
push和pop函數:
    我們來看一下比較重要的push和pop操作,可以這么來想,當有數據要入隊的時候,我們就讓它壓入stack1,要進行pop操作的時候,我們就把stack1里面的數據全部壓入stack2中,然后對stack進行一次pop操作就可以了,因為此時stack的棧頂就相當於隊列的最先進來的數據(當然在pop操作里需要先判斷兩個棧是否都為空,而且當stack2不為空的話就可以直接進行stack2.pop(),stack2為空但是stack1不為空在進行上面的操作)。
       再來看看上面的圖:我們就把1,2,3,4壓入s1中,當pop操作的時候,我們就把s1的元素都壓入到s2中,然后對s2進行pop操作就相當於對隊列的pop了。
                   
void push(const T& data)
    {
        s1.push(data);
    }
    void pop()
    {
        if (s1.empty() && s2.empty())
        {
            cout << "The queue is empty";
        }
        if (!s2.empty())
        {
            s2.pop();
        }
        else
        {
            while (!s1.empty())
            { 
                s2.push(s1.top());
                s1.pop();
            }
        }
    }

  看代碼,是否覺得很簡單。

front和back函數:
      再來看看它的front和back函數,前面也有提到,這個隊列的front就是stack2的棧頂元素,只要stack2不為空我們返回stack2的棧頂就可以,為空的話還是像之前一樣,我們把stack1的所有數據全部壓入stack2中再取棧頂。那么back取隊尾的操作如何實現呢,我們先來想想我么實現的這個隊列的隊尾在哪里。
      看下圖,情況一是當我的stack1的數據還沒有壓入stack2中的時候,stack1中的棧頂元素是最后一個壓入stack1的,也就相當於隊列的隊尾啊是不是,那么在stack1不為空的情況下只需要返回stack1的棧頂元素即s1.top()。情況二中是stack1為空,那么此時的隊尾應該是stack2的棧底,這樣的話我們又需要把stack2的元素全部壓入到s1中,stack2的棧底也就成了stack1的棧頂,再返回stack1
的棧頂就行。 其實還有一種是stack1和stack2都不為空的情況,這其實和情況一一個道理,直接返回s1.top()就OK.

                

T& Front()
    {
        assert(!s1.empty() || !s2.empty());
        if (s2.empty())
        {
            while (!s1.empty())
            {
                s2.push(s1.top());
                s1.pop();
            }
        }
        return s2.top();
    }
    T& Back()
    {
        assert(!s1.empty() || !s2.empty());
        if (s1.empty() )
        {
            while (!s2.empty())
            {
                s1.push(s2.top());
                s2.pop();
            }
        }
        return s1.top();
    }

  

empty和size:
      最后看看最簡單的empty()和size()函數,判斷隊列是否empty的話,那就是判斷我們用的兩個棧是否都為空,如果s1和s2都為空的話就返回true,否則返回false。size函數及返回兩個棧的size之和。

       最后附上本人的整體代碼,歡迎指正:

          

 1 #include<stack>
 2 template<typename T>
 3 class QueueBy2Stack
 4 {
 5 public:
 6 
 7     void push(const T& data)
 8     {
 9         s1.push(data);
10     }
11     void pop()
12     {
13         if (s1.empty() && s2.empty())
14         {
15             cout << "The queue is empty";
16         }
17         if (!s2.empty())
18         {
19             s2.pop();
20         }
21         else
22         {
23             while (!s1.empty())
24             { 
25                 s2.push(s1.top());
26                 s1.pop();
27             }
28             s2.pop();
29         }
30     }
31     T& Front()
32     {
33         assert(!s1.empty() || !s2.empty());
34         if (s2.empty())
35         {
36             while (!s1.empty())
37             {
38                 s2.push(s1.top());
39                 s1.pop();
40             }
41         }
42         return s2.top();
43     }
44     T& Back()
45     {
46         assert(!s1.empty() || !s2.empty());
47         if (s1.empty() )
48         {
49             while (!s2.empty())
50             {
51                 s1.push(s2.top());
52                 s2.pop();
53             }
54         }
55         return s1.top();
56     }
57     size_t size()
58     {
59         return s1.size() + s2.size();
60     }
61     bool empty()
62     {
63         if (s1.empty() && s2.empty())
64         {
65             return true;
66         }
67         return false;
68     }
69 private:
70     stack<T> s1;
71     stack<T> s2;
72 };

        文章作者:Mr_listening。 博客地址:http://www.cnblogs.com/MrListening/


免責聲明!

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



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