栈与队列理论基础 队列是先进先出,栈是先进后出
栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是我们可以控制使用哪种容器来实现栈的功能)
我们常用的SGL STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的底层结构。
栈提供push和pop接口,所有元素必须符合先进后出的规则,所以栈不提供走访功能,也不提供迭代器。不像set或者map提供迭代器iterator来遍历所有元素。
deque是一个双向队列,只要封住一段,只开通另一端就可以实现栈的逻辑了。
232.用栈实现队列 文章:2. 用栈实现队列
题目:232. 用栈实现队列
视频:栈的基本操作! | LeetCode:232.用栈实现队列_哔哩哔哩_bilibili
使用栈实现队列的下列操作:
push(x) – 将一个元素放入队列的尾部。 pop() – 从队列首部移除元素。 peek() – 返回队列首部的元素。 empty() – 返回队列是否为空。
【思路】
队列:先入先出
栈,需要借助另一个栈。关键在于如何模拟出栈的顺序,需要两个栈,一个输入栈,一个输出栈。
在push数据的时候,只要数据全部放进输入栈就好,但在pop的时候,就要把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。
最后如何判断队列为空?如果进栈和出栈队列都为空的话, 说明模拟的队列也为空了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class MyQueue { Stack<Integer> stackIn; Stack<Integer> stackOut; public MyQueue () { stackIn = new Stack <>(); stackOut = new Stack <>(); } public void push (int x) { stackIn.push(x); } public int pop () { dumpstackIn(); return stackOut.pop(); } public int peek () { dumpstackIn(); return stackOut.peek(); } public boolean empty () { return stackIn.isEmpty()&&stackOut.isEmpty(); } private void dumpstackIn () { if (!stackOut.isEmpty()){ return ; } while (!stackIn.isEmpty()){ stackOut.push(stackIn.pop()); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 type MyQueue struct { stackIn []int stackOut []int } func Constructor () MyQueue { return MyQueue{ stackIn: make ([]int ,0 ), stackOut: make ([]int ,0 ), } } func (this *MyQueue) Push(x int ) { this.stackIn = append (this.stackIn,x) } func (this *MyQueue) Pop() int { inlen , outlen := len (this.stackIn),len (this.stackOut) if outlen == 0 { if inlen == 0 { return -1 } for i:=inlen-1 ;i>=0 ;i--{ this.stackOut = append (this.stackOut,this.stackIn[i]) } outlen = len (this.stackOut) this.stackIn = []int {} } val := this.stackOut[outlen-1 ] this.stackOut = this.stackOut[:outlen-1 ] return val } func (this *MyQueue) Peek() int { val := this.Pop() if val == -1 { return -1 } this.stackOut = append (this.stackOut,val) return val } func (this *MyQueue) Empty() bool { return len (this.stackIn) == 0 && len (this.stackOut)==0 }
225.用队列实现栈 文章:3. 用队列实现栈
题目:225. 用队列实现栈
视频:队列的基本操作! | LeetCode:225. 用队列实现栈_哔哩哔哩_bilibili
【思路】
用一个队列来模拟栈的进出。
把元素提出来再加入队列即可。
使用了Deque
类型来完成该题,使用的函数有:
addLast()
添加至队列最后元素
peekFirst()
查看顶层元素
pollFirst()
弹出顶层元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class MyStack { Deque<Integer> que1; public MyStack () { que1 = new ArrayDeque <>(); } public void push (int x) { que1.addLast(x); } public int pop () { int size = que1.size(); size--; while (size-- >0 ){ que1.addLast(que1.peekFirst()); que1.pollFirst(); } int res = que1.pollFirst(); return res; } public int top () { return que1.peekLast(); } public boolean empty () { return que1.isEmpty(); } }
使用了切片模拟队列来进行入栈出栈的操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 type MyStack struct { queue []int } func Constructor () MyStack { return MyStack{ queue: make ([]int ,0 ), } } func (this *MyStack) Push(x int ) { this.queue = append (this.queue,x) } func (this *MyStack) Pop() int { l := len (this.queue)-1 for l != 0 { val := this.queue[0 ] this.queue = this.queue[1 :] this.queue = append (this.queue,val) l-- } val := this.queue[0 ] this.queue = this.queue[1 :] return val } func (this *MyStack) Top() int { val := this.Pop(); this.queue = append (this.queue,val) return val } func (this *MyStack) Empty() bool { return len (this.queue) == 0 }
【算法总结】
用栈实现队列:使用了两个栈(输入栈和输出栈)来模拟队列的操作,将输入栈的内容顺序放出输出栈即为队列的形式。
用队列实现栈:使用了一个队列来模拟栈的操作,将队列的元素弹出后再放入,循环下来即模拟了栈的形式。
【语法总结】
Java使用了Stack
和Deque
来模拟队列和栈:
栈(Stack)的函数:
push(x)
– 将一个元素放入队列的尾部。 pop()
– 从队列首部移除元素。 peek()
– 返回队列首部的元素。 empty()
– 返回队列是否为空。
队列(Deque)的函数-
addLast()
添加至队列最后元素
peekFirst()
查看顶层元素
pollFirst()
弹出顶层元素
Go使用了切片来模拟队列和栈,还是相对来说非常灵活的。