栈与队列的理论基础
LeetCode 232.用栈实现队列
-
思路:
- 这是一道模拟的题,并没有涉及到具体的算法思想,考察的只是对栈和队列的掌握程度。
- 栈是先进后出,队列是先进先出的,如果只用一个栈,是无法实现队列的,所以我们不妨考虑两个栈来实现。定义2个栈,一个输入栈,一个输出栈。
- 输入push() :输入时,直接使用输入栈的push() ;即可完成输入
- 弹出pop() : 相对复杂一些的是pop(),需要用到输入栈、输出栈。必须是输出栈为空时,输入栈弹出给输出栈,此时元素顺序就达到“先进先出”的要求了。弹出栈不为空,就操作输出栈的,也是“先进先出”的要求。
- peek() : 获取队列的首个元素值。我们可以使用刚才定义的pop函数 ,int res = this->pop(); 用res接住弹出的首个的值,然后我们再把res的接住的值送回给输出栈,毕竟它从输出栈出来的。最后return res,即可实现获取队列的首个元素值。
-
代码:
class MyQueue { public: stack<int> stIn; stack<int> stOut; MyQueue() { } void push(int x) { //输入一个数,直接用stIn的push就可以了 stIn.push(x); } int pop() { //只有stOut为空时,才从stIn导入 if(stOut.empty()) { //输入栈里不为空,就一直把输入栈里的数据放进输出栈 while(!stIn.empty()){ //把stIn的top()给stOut, stOut.push(stIn.top()); // stIn弹出 stIn.pop(); } } int result = stOut.top(); //从输出栈里弹出顶部数据 stOut.pop(); return result; } int peek() { int res = this->pop();// 直接使用已有的pop函数 stOut.push(res); //再把弹出的res的值,送回stOut里 return res; } bool empty() { return stIn.empty() && stOut.empty(); } };
-
收获:
- 代码的复用,把经常要用到的函数功能专门写出来,要用的时候就直接调用就好了,不用每次都复制一遍该部分功能代码。本题里peek()函数的实现,就复用了pop()。
LeetCode 225. 用队列实现栈
-
思路:
- 这也是一道模拟的题,并没有涉及到具体的算法思想,考察的是对栈和队列的掌握程度。
- 队列是先进先出的规则。2个队列的话,把一个队列中的数据导入另一个队列后再导出,数据的顺序并没有变,并没有变成先进后出的顺序。所以还是用一个队列来实现栈的操作。
- 输入push() : 输入一个数据,直接使用队列的push() 即可以 完成栈的元素的输入。
- 弹出pop() :队列是先进先出,而栈是先进后出的。队列中的pop()是对首元素操作的,而栈想实现的pop() 在队列中却是队列的尾元素 。
- 所以设队列元素长度为size,除了要弹出的 队列的最后一个元素外,是不是可以先一边弹出队列的元素、一边 把弹出的这个数据送回队列,直到操作了size -1 次后,原本队列中的尾元素就到了队列的头位置,此时进行弹出操作, 就是栈想要实现的pop函数。
- 顶部元素top() : 因为栈的顶部元素,其实是最后一个进入栈的元素,所以对于队列来说,最后一个元素就是queue.back()
-
代码:
class MyStack { public: queue <int>que; MyStack() { } //入栈 void push(int x) { que.push(x); } //出栈 int pop() { //获取长度size int size = que.size(); size--; // 得到size-1,在下面有用,弹出又送进size-1个元素 while(size--) { que.push(que.front()); que.pop(); } int res = que.front(); que.pop(); return res; } //栈的首个元素,其实是队列的尾元素 int top() { return que.back(); } bool empty() { return que.empty(); } };
-
总结:
做了上面的 “用队列实现栈”,再看这题就简单很多了。