本篇任务
前篇我们分别介绍了栈和队列,并对其进行了简单的自我实现,本篇我们将通过栈和队列的相互实现来进一步熟悉和运用栈和队列,如下是我们将要完成的题目:
用队列实现栈https://leetcode-cn.com/problems/implement-stack-using-queues/
用栈实现队列https://leetcode-cn.com/problems/implement-queue-using-stacks/
问题描述
实现 MyQueue
类和 MyStack
类::
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
说明:
- 你只能使用标准的栈操作 —— 也就是只有
push to top
,peek/pop from top
,size
, 和is empty
操作是合法的。 - 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
不论是用队列模拟栈,还是用栈模拟队列,我们都会发现使用 poll 方法取出元素时,栈 Stack 从顶部取出即 34 ,而队列则从队头取出 12
原因分析:
使用一个栈来模拟队列时,所有元素都会被推入栈中,这意味着后入栈的元素会先出栈,与队列的先进先出特性不符。使用一个队列模拟栈时情况于此相反。那么如何解决这个问题呢?。
解决方案:
为了实现队列的先进先出(FIFO)特性,我们通常会使用两个栈来模拟队列。一个栈用于入队操作,将元素按顺序推入栈中。另一个栈用于出队操作,当需要出队时,将入队栈中的元素依次弹出并推入出队栈中,然后从出队栈中弹出元素即可实现队列的先进先出特性。
创建两个栈,Queue1 和 Queue2 ,向栈中添加元素时,同样向 Queue1 中添加,当模拟出栈操作时,将 Queue1 队列中除了最后一个元素之外的所有元素,逐个出队并入队到 Queue2 队列中。然后将 Queue1 队列中的最后一个元素出队,即为栈Q顶元素。
其余操作依次类推,将数据不断在 Queue1 和 Queue2 中转换即可,代码实现如下:
public class MyStackByQueue {
public Queue<Integer> que1;
public Queue<Integer> que2;
public MyStackByQueue() {
que1=new LinkedList<>();
que2=new LinkedList<>();
}
public void push(int x) {
if(!que1.isEmpty()) {
que1.offer(x);
}else if(!que2.isEmpty()) {
que2.offer(x);
}else {
que1.offer(x);
}
}
public int pop() {
if(empty()){
return -1;
}
if(!que1.isEmpty()){
int size= que1.size()-1;
for(int i=0;i<size;i++){
que2.offer(que1.poll());
}
return que1.poll();
}else{
int size=que2.size()-1;
for(int i=0;i<size;i++){
que1.offer(que2.poll());
}
return que2.poll();
}
}
public int top() {
int val=0;
if(empty()){
return -1;
}
if(!que1.isEmpty()){
int size=que1.size();
for(int i=0;i<size;i++){
val=que1.poll();
que2.offer(val);
}
return val;
}else{
int size= que2.size();
for(int i=0;i<size;i++){
val=que2.poll();
que1.offer(val);
}
return val;
}
}
public boolean empty() {
return que1.isEmpty()&&que2.isEmpty();
}
}
为了满足栈的后进先出(FOFI)Q的特性,通常使用两个队列实现栈Q。入栈操作时,将元素添加到非空的队列末尾;出栈操作时,将非空队列中的元素逐个取出并加入空队列,直到取出待出栈元素,然后将非空队列和空队列的角色互换,以便下一次操作。这样就可以实现栈的后进先出的效果
定义两个链栈Stack1和Stack2,其中Stack1用于入队操作,Stack2用于出队操作。入队操作时,直接将元素压入Stack1即可。出队操作时,首先判断Stack2是否为空。若不为空,则直接弹出Stack2的栈顶元素即为出队元素;若为空,则将Stack1中的所有元素逐个弹出并压入Stack2,然后弹出Stack2的栈顶元素。
代码实现如下: ( top() 换为 peek() )
public class MyQueueByStack {
public Deque<Integer> st1;
public Deque<Integer> st2;
public MyQueueByStack() {
st1=new LinkedList<>();
st2=new LinkedList<>();
}
public void push(int x) {
st1.offer(x);
}
public int pop() {
if(empty()){
return -1;
}
if(!st1.isEmpty()){
int size=st1.size();
for(int i=0;i<size;i++){
st2.offer(st1.poll());
}
}
return st2.poll();
}
public int peek() {
if(empty()){
return -1;
}
if(!st1.isEmpty()){
int size=st1.size();
for(int i=0;i<size;i++){
st2.offer(st1.poll());
}
}
return st2.peek();
}
public boolean empty() {
return st1.isEmpty()&&st2.isEmpty();
}
}
到这里本篇就圆满完成!有问题或不懂之处欢迎在评论区提出