剑指offer——stack与queue的互相实现

时间:2022-06-05 17:40:12

我们知道,stack和queue是C++中常见的container。下面,我们来探究下如何以stack来实现queue,以及如何用queue来实现stack。

首先,先了解下stack与queue的基本属性。

一、stack

  1,参数要求

     stack模板类需要两个参数:一个元素类型,一个容器类型。容器类型缺省为deque。

  2,基本操作

    入栈:s.push(element);element加入栈顶。

    出栈:s.pop(),栈顶元素被删除,无返回值。

    访问栈顶:s.top()。取得栈顶元素。

    判断栈空:s.empty()。栈空,返回true;非空,返回false。

    长度判断:s.size()。返回栈张元素个数

二、queue

  1,参数要求

    queue模板类需要两个参数:一个元素类型,一个容器类型。容器类型缺省为deque。

  2,基本操作

    入队:q.push(element)。element加入到队列的末端。

    出对:q.pop()。弹出(删除)队列的第一个元素(q.front())。无返回值。

    访问队首:q.front(), 即最早被压入队列的元素。

    访问队尾:q.back(),即最后被压入队列的元素。

    判断队空:q.empty()。队空,返回true。

    长度判断:q.size()。返回队列中元素个数。

三、两个stack实现queue

  在基本了解了stack和queue这两个container后,我们来看看如何用stack实现queue。

  如上所诉,queue包含了push(), pop(),front(),back(),empty()这些基本操作,现在的问题 就是如何用stack实现这些操作。

  1,分析(已知stack A 和stack B)

   入队:将元素进栈A

   出队:判断B是否为空,如果为空,则将栈A中所有元素pop, 并push进 栈B,栈B出栈。

   访问队首:栈B的栈顶。

   访问队尾:如果栈A非空,队尾即栈A的栈顶(A.top());如果栈A为空,队尾为栈B的栈底(怎么取得栈B的栈底?利用第三个stack??

   队空:两个栈空,则队空。

   长度:A.size(),  B.size()

  2,示意代码(未实现back())

剑指offer——stack与queue的互相实现剑指offer——stack与queue的互相实现
 1 class Stack2queue {
 2 public:
 3     void push(int node) {
 4         stack1.push(node);
 5     }
 6 
 7     void pop() {
 8         if (stack2.empty()) {
 9             if (stack1.empty())
10                 throw runtime_error("No elements");
11             else {
12                 while (!stack1.empty()) {
13                     stack2.push(stack1.top());
14                     stack1.pop();
15                 }
16                 stack2.pop();
17             }
18 
19         }else
20             stack2.pop();
21     }
22     int front() {
23         if (stack2.empty()) {
24             if (stack1.empty())
25                 throw runtime_error("No elements");
26             else {
27                 while (!stack1.empty()) {
28                     stack2.push(stack1.top());
29                     stack1.pop();
30                 }
31                 return stack2.top();
32             }
33 
34         }else
35             return stack2.top();
36     }
37 
38     bool myEmpty() {
39         if (stack1.empty() && stack2.empty())
40             return true;
41         else
42             return false;
43     }
44 private:
45     stack<int> stack1;
46     stack<int> stack2;
47 };
View Code

    示意代码中未实现back()操作,笔者的想法是:若栈A为空,将stack B的元素pop出来,再push进 stack C。C的栈顶元素即是队尾。但是这样就新增了一个stack。不知道给广大博友是否有更好的方法?

四、两个queue实现stack

  1,分析(queue A 和 queue B)

     入栈:将元素push进队列A

     出栈:判断队列A是否为空。空,则把队列B的元素出队列,进队列A,A再出队列进队列B,直到A中元素剩1,然后A.pop();非空,队列A中元素出队列进队列B,直到A中元素剩1,然后A.pop().

    访问栈顶:与出栈类似,只不过由A.pop()B变为了A.front()或A.back(), 因为此时A只剩下一个元素。

    判断栈空:queue1.empty() && queue2.empty()

    长度:queue1.size() + queue2.size()

  2,示意代码

剑指offer——stack与queue的互相实现剑指offer——stack与queue的互相实现
 1 class Queue2stack {
 2 public:
 3     void push(int);
 4     void pop();
 5     int top();
 6     bool myempty();
 7 private:
 8     queue<int> queue1;
 9     queue<int> queue2;
10 };
11 void Queue2stack::push(int element) {
12     queue1.push(element);
13 }
14 
15 void Queue2stack::pop() {
16     if(!queue1.empty()) {
17         while(queue1.size() > 1) {
18             queue2.push(queue1.front());
19             queue1.pop();
20         }
21         queue1.pop();
22 
23     }
24     else {
25         if(!queue2.empty()) {
26             while (!queue2.empty()) {
27                 queue1.push(queue2.front());
28                 queue2.pop();
29             }
30             while(queue1.size() > 1) {
31                 queue2.push(queue1.front());
32                 queue1.pop();
33             }
34             queue1.pop();
35         }
36 
37     }
38 }
39 
40 int Queue2stack::top() {
41     if(!queue1.empty()) {
42         while(queue1.size() > 1) {
43             queue2.push(queue1.front());
44             queue1.pop();
45         }
46         return queue1.back();
47 
48     }
49     else {
50         if(!queue2.empty()) {
51             while (!queue2.empty()) {
52                 queue1.push(queue2.front());
53                 queue2.pop();
54             }
55             while(queue1.size() > 1) {
56                 queue2.push(queue1.front());
57                 queue1.pop();
58             }
59             return queue1.back();
60         }
61     }
62     throw runtime_error("No elements!");
63 
64 }
65 
66 bool Queue2stack::myempty() {
67     if(queue1.empty() && queue2.empty())
68         return true;
69     else
70         return false;
71 }
View Code

五、综合测试

  上述讨论,介绍了stack和queue的相互实现。下面这个例子来检测我们的算法是否正确。

剑指offer——stack与queue的互相实现剑指offer——stack与queue的互相实现
  1 #include <iostream>
  2 #include <stack>
  3 #include <queue>
  4 using namespace std;
  5 
  6 class Stack2queue {
  7 public:
  8     void push(int node) {
  9         stack1.push(node);
 10     }
 11 
 12     void pop() {
 13         if (stack2.empty()) {
 14             if (stack1.empty())
 15                 throw runtime_error("No elements");
 16             else {
 17                 while (!stack1.empty()) {
 18                     stack2.push(stack1.top());
 19                     stack1.pop();
 20                 }
 21                 stack2.pop();
 22             }
 23 
 24         }else
 25             stack2.pop();
 26     }
 27     int front() {
 28         if (stack2.empty()) {
 29             if (stack1.empty())
 30                 throw runtime_error("No elements");
 31             else {
 32                 while (!stack1.empty()) {
 33                     stack2.push(stack1.top());
 34                     stack1.pop();
 35                 }
 36                 return stack2.top();
 37             }
 38 
 39         }else
 40             return stack2.top();
 41     }
 42 
 43     bool myEmpty() {
 44         if (stack1.empty() && stack2.empty())
 45             return true;
 46         else
 47             return false;
 48     }
 49 private:
 50     stack<int> stack1;
 51     stack<int> stack2;
 52 };
 53 
 54 class Queue2stack {
 55 public:
 56     void push(int);
 57     void pop();
 58     int top();
 59     bool myempty();
 60 private:
 61     queue<int> queue1;
 62     queue<int> queue2;
 63 };
 64 void Queue2stack::push(int element) {
 65     queue1.push(element);
 66 }
 67 
 68 void Queue2stack::pop() {
 69     if(!queue1.empty()) {
 70         while(queue1.size() > 1) {
 71             queue2.push(queue1.front());
 72             queue1.pop();
 73         }
 74         queue1.pop();
 75 
 76     }
 77     else {
 78         if(!queue2.empty()) {
 79             while (!queue2.empty()) {
 80                 queue1.push(queue2.front());
 81                 queue2.pop();
 82             }
 83             while(queue1.size() > 1) {
 84                 queue2.push(queue1.front());
 85                 queue1.pop();
 86             }
 87             queue1.pop();
 88         }
 89 
 90     }
 91 }
 92 
 93 int Queue2stack::top() {
 94     if(!queue1.empty()) {
 95         while(queue1.size() > 1) {
 96             queue2.push(queue1.front());
 97             queue1.pop();
 98         }
 99         return queue1.back();
100 
101     }
102     else {
103         if(!queue2.empty()) {
104             while (!queue2.empty()) {
105                 queue1.push(queue2.front());
106                 queue2.pop();
107             }
108             while(queue1.size() > 1) {
109                 queue2.push(queue1.front());
110                 queue1.pop();
111             }
112             return queue1.back();
113         }
114     }
115     throw runtime_error("No elements!");
116 
117 }
118 
119 bool Queue2stack::myempty() {
120     if(queue1.empty() && queue2.empty())
121         return true;
122     else
123         return false;
124 }
125 int main()
126 {
127     // stack to queue
128     Stack2queue s2q;
129     for (int i = 1; i < 10; ++i) {
130         s2q.push(i);
131     }
132     while (!s2q.myEmpty()) {
133         cout << s2q.front() << ' ';
134         s2q.pop();
135     }
136 
137     //queue to stack
138     cout << endl;
139     Queue2stack q2s;
140     for (int i = 1; i < 10; ++i) {
141         q2s.push(i);
142     }
143     while(!q2s.myempty()) {
144         cout << q2s.top() << ' ';
145         q2s.pop();
146     }
147     //system("pause");
148     return 0;
149 }
View Code

  实验结果:

  剑指offer——stack与queue的互相实现

  我们看到,我们很好的用stack模拟了queue,达到了先进先出的效果;同样,我们也很好的用queue模拟了stack,先进后出的效果。

  不过,值得考虑的是,笔者在用stack实现queue时,没有实现back()操作。各位博友有啥好想法呢?