编程算法学习——栈与队列算法

目录

一、核心原理:栈(LIFO)与队列(FIFO)

[1. 栈(Stack)------ 后进先出(Last In First Out)](#1. 栈(Stack)—— 后进先出(Last In First Out))

[2. 队列(Queue)------ 先进先出(First In First Out)](#2. 队列(Queue)—— 先进先出(First In First Out))

二、栈的典型应用:括号匹配

[1. 问题场景](#1. 问题场景)

[2. 解题思路](#2. 解题思路)

[3. 代码实现(Java)](#3. 代码实现(Java))

[4. 代码关键解释](#4. 代码关键解释)

三、队列的典型应用:二叉树层次遍历

[1. 问题场景](#1. 问题场景)

[2. 解题思路](#2. 解题思路)

[3. 代码实现(Java)](#3. 代码实现(Java))

[4. 代码关键解释](#4. 代码关键解释)

四、总结

关键点回顾


栈与队列 ------从原理到实战

一、核心原理:栈(LIFO)与队列(FIFO)

1. 栈(Stack)------ 后进先出(Last In First Out)

  • 通俗理解:像叠盘子,最后放上去的盘子,最先被拿走;只能从「栈顶」操作元素(入栈 / 出栈)。
  • 核心操作
    • push():入栈(向栈顶添加元素)
    • pop():出栈(从栈顶移除元素,返回该元素)
    • peek():查看栈顶元素(不移除)
    • isEmpty():判断栈是否为空
  • Java 实现 :推荐使用 Deque(双端队列)代替过时的 Stack 类(Stack 是遗留类,线程安全但性能差),Dequepush()/pop() 方法可模拟栈。

2. 队列(Queue)------ 先进先出(First In First Out)

  • 通俗理解:像排队买票,最先排队的人,最先买到票;只能从「队尾」入队,「队首」出队。
  • 核心操作
    • offer():入队(向队尾添加元素,失败返回 false,比 add() 更安全)
    • poll():出队(从队首移除元素,返回该元素,队列为空返回 null)
    • peek():查看队首元素(不移除)
    • isEmpty():判断队列是否为空
  • Java 实现 :常用 LinkedList 实现 Queue 接口(LinkedList 同时实现了 ListDeque)。

二、栈的典型应用:括号匹配

1. 问题场景

判断一个字符串中的括号是否合法匹配,例如:

  • 合法:()[]{}, ({[]})
  • 非法:(], ([)], {}(少左括号), ({}(少右括号)

2. 解题思路

  1. 遍历字符串的每个字符;
  2. 遇到左括号(/[/{),直接入栈;
  3. 遇到右括号
    • 如果栈为空(无左括号匹配),直接返回 false
    • 弹出栈顶元素,判断是否与当前右括号「成对」,不成对则返回 false
  4. 遍历结束后,若栈不为空(有未匹配的左括号),返回 false;否则返回 true

3. 代码实现(Java)

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

/**
 * 栈实现括号匹配
 */
public class BracketMatch {
    public static boolean isValid(String s) {
        // 1. 初始化双端队列作为栈(推荐用法)
        Deque<Character> stack = new LinkedList<>();
        
        // 2. 遍历字符串每个字符
        for (char c : s.toCharArray()) {
            // 3. 左括号入栈
            if (c == '(' || c == '[' || c == '{') {
                stack.push(c);
            } else {
                // 4. 右括号:先判断栈是否为空(无左括号匹配)
                if (stack.isEmpty()) {
                    return false;
                }
                // 5. 弹出栈顶元素,判断是否匹配
                char top = stack.pop();
                if ((c == ')' && top != '(') || 
                    (c == ']' && top != '[') || 
                    (c == '}' && top != '{')) {
                    return false;
                }
            }
        }
        // 6. 遍历结束后,栈必须为空(无剩余左括号)
        return stack.isEmpty();
    }

    // 测试用例
    public static void main(String[] args) {
        System.out.println(isValid("()[]{}"));   // true
        System.out.println(isValid("(]"));       // false
        System.out.println(isValid("({[]})"));   // true
        System.out.println(isValid("({})"));     // true
        System.out.println(isValid("{"));        // false
    }
}

4. 代码关键解释

  • Deque<Character> stack = new LinkedList<>():用 LinkedList 实现 Deque,模拟栈(比原生 Stack 更优);
  • 右括号处理逻辑:先判空再弹栈,避免空栈调用pop()抛出异常;
  • 最终栈为空的判断:确保所有左括号都有对应的右括号匹配(比如"({"遍历完栈不为空,返回 false)。

三、队列的典型应用:二叉树层次遍历

1. 问题场景

二叉树的层次遍历(广度优先遍历 / BFS):按从上到下、从左到右的顺序,逐层输出二叉树的节点值。

例如:

java 复制代码
    1
   / \
  2   3
 / \   \
4   5   6

层次遍历结果:[1, 2, 3, 4, 5, 6](或按层分组:[[1], [2,3], [4,5,6]])。

2. 解题思路

  1. 初始化队列,将根节点入队;
  2. 循环处理队列:
    • 记录当前队列的大小(即当前层的节点数);
    • 遍历当前层的所有节点:弹出队首节点,记录值;
    • 若节点有左子节点,入队;若有右子节点,入队;
  3. 直到队列为空,结束遍历。

3. 代码实现(Java)

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

/**
 * 队列实现二叉树层次遍历(按层输出)
 */
// 首先定义二叉树节点类
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public class LevelOrderTraversal {
    public static List<List<Integer>> levelOrder(TreeNode root) {
        // 结果集合:每个子List存储一层的节点值
        List<List<Integer>> result = new ArrayList<>();
        // 边界条件:根节点为空,直接返回空集合
        if (root == null) {
            return result;
        }

        // 1. 初始化队列,根节点入队
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        // 2. 循环处理队列
        while (!queue.isEmpty()) {
            // 当前层的节点数(关键:队列当前的大小就是当前层的节点数)
            int levelSize = queue.size();
            // 存储当前层的节点值
            List<Integer> currentLevel = new ArrayList<>();

            // 3. 遍历当前层的所有节点
            for (int i = 0; i < levelSize; i++) {
                // 弹出队首节点
                TreeNode node = queue.poll();
                // 记录当前节点值
                currentLevel.add(node.val);

                // 4. 左子节点入队(非空才入队)
                if (node.left != null) {
                    queue.offer(node.left);
                }
                // 右子节点入队(非空才入队)
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            // 将当前层的结果加入总结果
            result.add(currentLevel);
        }
        return result;
    }

    // 测试用例:构建示例二叉树并测试
    public static void main(String[] args) {
        // 构建二叉树
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(4);
        root.left.right = new TreeNode(5);
        root.right.right = new TreeNode(6);

        // 层次遍历
        List<List<Integer>> result = levelOrder(root);
        // 输出结果:[[1], [2, 3], [4, 5, 6]]
        System.out.println(result);
    }
}

4. 代码关键解释

  • TreeNode 类:二叉树节点的标准定义,包含值、左子节点、右子节点;
  • levelSize = queue.size():每次循环先记录当前队列大小,确保只处理当前层的节点(避免跨层);
  • 子节点入队判断:只将非空的子节点入队,避免处理空节点;
  • 结果按层存储:List<List<Integer>> 结构更直观体现「层次」特性,也是面试中常见要求。

四、总结

关键点回顾

  1. 核心特性 :栈是「后进先出(LIFO)」,队列是「先进先出(FIFO)」,Java 中推荐用Deque实现栈、LinkedList实现队列;
  2. 栈的核心应用:括号匹配的关键是「左括号入栈,右括号匹配栈顶」,遍历结束后栈必须为空;
  3. 队列的核心应用 :二叉树层次遍历的关键是「按层处理队列」,通过queue.size()控制每层的节点数,实现逐层输出。
相关推荐
CSDN_Colinw2 小时前
C++中的工厂方法模式
开发语言·c++·算法
liulilittle2 小时前
范围随机算法实现
开发语言·c++·算法·lua·c·js
ADHD多动联盟2 小时前
什么是儿童ADHD的运动干预方案?主要有怎样的应对分心走神的疗法?
学习·学习方法·玩游戏
2501_918126912 小时前
学习所有6502写游戏地图的语句
汇编·嵌入式硬件·学习·游戏·个人开发
2401_857918292 小时前
C++中的访问者模式实战
开发语言·c++·算法
elseif1232 小时前
CSP-S提高级大纲
开发语言·数据结构·c++·笔记·算法·大纲·考纲
熊猫_豆豆3 小时前
Python 基于Dlib和OpenCV实现人脸融合算法+代码
图像处理·python·算法·人脸融合
sheji34163 小时前
【开题答辩全过程】以 基于微信小程序的少儿编程学习平台为例,包含答辩的问题和答案
学习·微信小程序·小程序
Book思议-3 小时前
【数据结构实战】双向链表:在指定位置插入数据
c语言·数据结构·算法·链表