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

     拿到這種問題,咱們首先應該思考這兩種結構的特性是什麼,爲何會出這樣的題。其實就說明這二者的特性是有某種聯繫的,這麼想的話其實很簡單,棧的最大特色就是先進後出,讓咱們用兩個先進後出的棧來實現一個先進先出的隊列,那麼咱們把數據壓入第一個棧,此時咱們很清楚它的出戰順序是與咱們想要的隊列的出隊順序是相反的,若是再把這個棧裏面的元素依次壓入第二個棧,此時咱們想一想棧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之和。

       最後附上本人的總體代碼,歡迎指正:spa

          

 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/code

相關文章
相關標籤/搜索