【算法】简单讲解如何使用两个栈实现一个队列

简介: 【算法】简单讲解如何使用两个栈实现一个队列

什么是栈和队列?

栈和队列其实大家基本都知道是什么,或者说,最基本的,他们的特性我们是知道的。

栈是一种FILO先进后出的数据结构,队列是一种FIFO先进先出的数据结构。

那么其实他们两个是反过来的,那么,我们其实就可以通过两个栈,实现一个队列,下面是一个简单的代码,包含了add,poll,peek方法。

设计思路

具体的实现是,一个栈作为压入栈,在压入数据时只往这个栈中压入,几位stackPush,另一个栈作为弹出栈,在弹出数据时,只从这个栈中弹出,记为stackPop。

因为数据压入栈的时候,顺序是先进后出的。那么只要把 stackPush的数据再压入stackPop中,顺序就变回来了。例如,将1-5依次压入 stackPush,那么从stackIn的栈顶到栈底为 5-1,此时依次再将5-1倒入stackPop,那么从stackOut的栈顶到栈底就变成了1~5。再从 stackPop弹出时,顺序就像队列一样。

听起来虽然简单,实际上必须做到以下两点。

1.如果 stackPush要往是stackPop中压入粉据.那么必须一次性把 stackPush中的数据全部压

2.如果stackPop不为空,sctarkPuch绝对不能向 stackPop中压入数

违反了以上两点都会发生错误。

违反1的情况举例:

1-5依次压入 stackPush,stackPush的栈顶到栈底为5~1,从stackPush压入stackPop时,只将5和4压入了 stackPop,stackPush还剩下1、2、3没有压入。此时如果用户想进行弹出操作,那么4将最先弹出,与预想的队列顺序就不一致

违反2的情况举例:

1-5依次压入 stackPush,stackPush将所有的数据压入stackPop,此时从 stackPop的栈顶到栈底就变成了1-5。此时又有6-10依次压入 stackPush,stackPop不为空,stackPush不能向其中压入数据。如果违反2压入了stackPop,从 stackPop 的栈顶到栈底就变成了6-10、1~5。那么此时如果用户想进行弹出操作,6将最先弹出,与预想的队列顺序就不一致。

上面介绍了压入数据的注意事项。那么这个压入数据的操作在何时发生呢?

这个选择的时机可以有很多,调用add、poll和 peek三种方法中的任何一种时发生“压”入数据的行为都是可以的。只要满足如上提到的两点,就不会出错。具体实现请参看如下的代码,代码比较简单

代码实现

package com.base.learn.stack;
import com.sun.org.apache.bcel.internal.generic.PUSH;
import java.util.Stack;
/**
 * @author: 张锦标
 * @date: 2023/5/27 14:43
 * StackMakeQueue类
 * 使用两个栈形成一个队列
 * 支持队列的add poll peek
 */
public class StackMakeQueue {
    private Stack<Integer> stackPush = new Stack<>();
    private Stack<Integer> stackPop = new Stack<>();
    public void add(int num){
        stackPush.push(num);
        inToOut();
    }
    private void inToOut(){
        //只有空的时候才能把in的数据放入到out,不然顺序就乱了
        if (stackPop.empty()){
            while (!stackPush.empty()){
                stackPop.push(stackPush.pop());
            }
        }
    }
    public int poll(){
        if (stackPop.isEmpty() && stackPush.isEmpty()){
            throw new RuntimeException("栈中并没有数据");
        }
        //如果说in栈中有数据 但是out栈中没有 那么把数据移动到out栈中
        inToOut();
        return stackPop.pop();
    }
    public int peek(){
        if (stackPop.isEmpty() && stackPush.isEmpty()){
            throw new RuntimeException("栈中并没有数据");
        }
        //如果说in栈中有数据 但是out栈中没有 那么把数据移动到out栈中
        inToOut();
        return stackPop.peek();
    }
     public static void main(String[] args) {
        StackMakeQueue stackMakeQueue = new StackMakeQueue();
        stackMakeQueue.add(1);
        stackMakeQueue.add(2);
        stackMakeQueue.add(3);
        System.out.println(stackMakeQueue.poll());
        System.out.println(stackMakeQueue.poll());
        System.out.println(stackMakeQueue.poll());
    }
}


相关文章
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
55 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
1月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
28 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
15天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
算法
数据结构与算法二:栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式
这篇文章讲解了栈的基本概念及其应用,并详细介绍了中缀表达式转换为后缀表达式的算法和实现步骤。
43 3
|
1月前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
20 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
|
2月前
|
存储 算法 前端开发
深入理解操作系统:进程调度与优先级队列算法
【9月更文挑战第25天】在操作系统的复杂世界中,进程调度是维持系统稳定运行的核心机制之一。本文将深入探讨进程调度的基本概念,分析不同的进程调度算法,并着重介绍优先级队列算法的原理和实现。通过简洁明了的语言,我们将一起探索如何优化进程调度,提高操作系统的效率和响应速度。无论你是计算机科学的初学者还是希望深化理解的专业人士,这篇文章都将为你提供有价值的见解。
|
1月前
|
算法 C++
【算法单调栈】 矩形牛棚(C/C++)
【算法单调栈】 矩形牛棚(C/C++)
|
3月前
|
缓存 算法 Java
刷算法,你应该知道的队列经典应用
文章介绍了队列的基本特性和经典应用,包括如何用队列实现栈、使用优先级队列解决Top K问题,并通过LeetCode题目示例展示了队列在算法实现中的应用。
刷算法,你应该知道的队列经典应用
|
3月前
|
算法
【数据结构与算法】优先级队列
【数据结构与算法】优先级队列
15 0
|
3月前
|
存储 算法
【数据结构与算法】队列(顺序存储)
【数据结构与算法】队列(顺序存储)
30 0