[数据结构]栈和队列的互相模拟实现

前言:本文将简单介绍一下如何使用栈(stack)来模拟实现队列(queue)以及如何使用队列来模拟实现栈

栈的特性是后进先出,就像一个乒乓球筒,最后放进去的乒乓球一定是最先被倒出球筒的.

队列特性就是先进先出,每次pop或者peek操作都是从队列的顶部出队列

一,使用栈模拟实现队列

(一)如何实现?使用双栈法

要想使得栈中的元素每次poll能得到最先进的元素,可以使用两个栈,一个是输入栈stack1 ,另外一个是输出栈stack2

push的元素全部进入输入栈stack1 ,当进行出栈操作的时候,为了拿到我们最先放的元素,stack1中的元素全部出栈,然后依次压入stack2输出栈中,此时就会发现在stack1中原先位置处于最底部的元素就被调换到了stack2的栈顶位置,此时直接把stack.poll()就能拿到对应元素了

但是需要注意,不是每次进行出栈操作时,我们都需要进行一次上面的操作(把stack1的元素出栈,压入stack2) 而是在poll或者peek之前先进行一次stack2的判空操作, 如果stack2为空, 说明之前stack2中的元素被出完了,需要从stack1中再搬过来一点. 如果!stack2.isEmpty() 则直接从stack2的栈顶拿就好了

下面是一个简单的模拟实现

(二)代码参考

这是一个通过java代码实现的双栈模拟实现队列代码:

java 复制代码
import java.util.Stack;  
  
public class MyQueue {  
    private Stack<Integer> stackIn;  
    private Stack<Integer> stackOut;  
  
    public MyQueue() {  
        stackIn = new Stack<>();  
        stackOut = new Stack<>();  
    }  
  
    public void push(int num) {  
        stackIn.push(num);  
    }  
  
    public int pop() {  
        // 先确保输出栈有东西  
        dumpStack();  
        if (stackOut.isEmpty()) throw new RuntimeException("Queue is empty");  
        return stackOut.pop();  
    }  
  
    public int peek() {  
        dumpStack();  
        if (stackOut.isEmpty()) throw new RuntimeException("Queue is empty");  
        return stackOut.peek();  
    }  
  
    // 统一的"搬栈"逻辑  
    private void dumpStack() {  
        // 关键:只有输出栈为空时才搬运,否则会打乱顺序  
        if (stackOut.isEmpty()) {  
            while (!stackIn.isEmpty()) {  
                stackOut.push(stackIn.pop());  
            }  
        }  
    }  
  
    public int getSize() {  
        return stackIn.size() + stackOut.size();  
    }  
  
    public boolean isEmpty() {  
        return stackIn.isEmpty() && stackOut.isEmpty();  
    }  
  
    public static void main(String[] args) {  
        MyQueue myQueue = new MyQueue();  
        int[] nums = {1, 2, 3, 4, 5};  
        for (int x : nums) myQueue.push(x);  
  
        System.out.println(myQueue.pop());    // 1  
        System.out.println(myQueue.getSize()); // 4  
    }  
}

二,使用队列模拟实现栈

(一)如何实现?

为了让队列表现得像栈,我们只需要在queue每次push新元素时,把前面已经存在的元素依次出队,再重新入队排到新元素的后面 。这样,新加入的元素就永远被顶在了队列的最前端。

栈的每次push操作之后,都把前面n-1个元素移动到队尾,这是核心思想.那么那么是否可以在我们每次需要查看栈顶元素的时候来在进行上面的队列翻转操作呢?

  • 如果在pop的时候才进行翻转,则每次我们需要查看栈顶元素peek,或者出栈pop时都需要进行一次翻转操作,这个时间复杂度为O(n),但是push的时间复杂度降低为O(1),
  • 但是若是按照push时进行翻转操作,则只有push时的时间复杂度为O(n),查看栈顶,出栈的时间复杂度则为O(1).在频繁的操作栈中元素,查看栈顶元素的时候性能较高

(二)代码实现

java 复制代码
import java.util.LinkedList;
import java.util.Queue;

public class MyStack {
    private Queue<Integer> queue;

    // 初始化队列
    public MyStack() {
        queue = new LinkedList<>();
    }
    
    // 入栈操作
    public void push(int x) {
        // 1. 先记录当前队列里的元素个数
        int n = queue.size();
        
        // 2. 将新元素加入队尾
        queue.offer(x);
        
        // 3. 将新元素之前的所有元素依次出队,并重新加入队尾
        for (int i = 0; i < n; i++) {
            queue.offer(queue.poll());
        }
    }
    
    // 出栈操作
    public int pop() {
        // 此时队头元素就是最后加进来的元素,直接出队即可
        return queue.poll();
    }
    
    // 获取栈顶元素
    public int top() {
        return queue.peek();
    }
    
    // 判断栈是否为空
    public boolean empty() {
        return queue.isEmpty();
    }
}

有关栈和队列的互相模拟实现就简单到这里了,如有纰漏还请指出~~

相关推荐
计算机安禾2 小时前
【数据结构与算法】第6篇:线性表(二):单链表的实现(头插法、尾插法)
c语言·数据结构·学习·算法·链表·visual studio code·visual studio
2401_873204652 小时前
C++与Node.js集成
开发语言·c++·算法
☆5662 小时前
基于C++的区块链实现
开发语言·c++·算法
ysa0510302 小时前
迷宫传送[最短路径]
c++·笔记·算法·深度优先
左左右右左右摇晃2 小时前
数据结构——链表
数据结构·链表
计算机安禾2 小时前
【数据结构与算法】第5篇:线性表(一):顺序表(ArrayList)的实现与应用
c语言·开发语言·数据结构·c++·算法·visual studio code·visual studio
仰泳的熊猫2 小时前
题目2584:蓝桥杯2020年第十一届省赛真题-数字三角形
数据结构·c++·算法·蓝桥杯
2401_864959282 小时前
C++与Python混合编程实战
开发语言·c++·算法
2501_945424802 小时前
C++与硬件交互编程
开发语言·c++·算法