栈的经典面试题之用两个栈实现一个队列

     拿到这种问题,咱们首先应该思考这两种结构的特性是什么,为何会出这样的题。其实就说明这二者的特性是有某种联系的,这么想的话其实很简单,栈的最大特色就是先进后出,让咱们用两个先进后出的栈来实现一个先进先出的队列,那么咱们把数据压入第一个栈,此时咱们很清楚它的出战顺序是与咱们想要的队列的出队顺序是相反的,若是再把这个栈里面的元素依次压入第二个栈,此时咱们想一想栈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

相关文章
相关标签/搜索