首页 > Java > java教程 > 正文

java代码怎样实现栈的括号匹配功能 java代码栈应用场景的实现方法​

爱谁谁
发布: 2025-08-11 22:25:01
原创
391人浏览过

java中栈的典型应用场景包括函数调用管理、表达式求值、撤销/重做功能、浏览器历史记录和深度优先遍历;2. 实现后缀表达式求值器时,遍历表达式,数字压栈,运算符弹出两个操作数计算后将结果压栈,最终栈中唯一元素为结果;3. 使用栈时应优先选用deque接口的arraydeque实现而非stack类,避免同步开销,并注意检查栈空状态以防止异常,同时警惕递归导致的栈溢出错误,多线程环境下可选用并发安全的集合类,这些实践能提升性能与代码健壮性。

java代码怎样实现栈的括号匹配功能 java代码栈应用场景的实现方法​

在Java中,实现括号匹配功能,栈是不可或缺的利器。其核心思想在于,当遇到开括号时将其压入栈中,遇到闭括号时则尝试与栈顶的开括号进行配对。栈在Java编程中应用广泛,尤其擅长处理需要后进先出(LIFO)逻辑的场景,比如表达式求值、函数调用管理等。

解决方案

实现括号匹配,我通常会用Java的

java.util.Deque
登录后复制
接口,因为它比传统的
Stack
登录后复制
类更推荐,性能更好,也更灵活。

我的做法是:

立即学习Java免费学习笔记(深入)”;

  1. 遍历输入字符串,遇到左括号(
    (
    登录后复制
    [
    登录后复制
    {
    登录后复制
    )就压栈。
  2. 遇到右括号,先检查栈是否为空。如果为空,那肯定是匹配失败了,比如多了一个右括号。
  3. 如果不为空,就弹出栈顶元素,看它是不是当前右括号对应的左括号。不是?失败。
  4. 遍历完所有字符后,如果栈里还有元素,说明有些左括号没被匹配,比如少了一个右括号,那也是失败。
  5. 最后,栈为空才算成功。

这是一个具体的实现示例:

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;

public class ParenthesisMatcher {

    public boolean isValid(String s) {
        // 使用ArrayDeque作为栈,比java.util.Stack更推荐
        Deque<Character> stack = new ArrayDeque<>();
        // 预设匹配规则,方便查找
        Map<Character, Character> mappings = new HashMap<>();
        mappings.put(')', '(');
        mappings.put('}', '{');
        mappings.put(']', '[');

        for (char c : s.toCharArray()) {
            if (mappings.containsKey(c)) { // 如果是右括号
                // 栈为空或栈顶元素不匹配,则无效
                if (stack.isEmpty() || stack.pop() != mappings.get(c)) {
                    return false;
                }
            } else { // 如果是左括号,压入栈中
                stack.push(c);
            }
        }

        // 遍历完所有字符后,如果栈为空,则所有括号都已匹配
        return stack.isEmpty();
    }

    // 可以在这里添加一个main方法测试
    public static void main(String[] args) {
        ParenthesisMatcher matcher = new ParenthesisMatcher();
        System.out.println("()[]{} is valid: " + matcher.isValid("()[]{}")); // true
        System.out.println("([{}]) is valid: " + matcher.isValid("([{}])")); // true
        System.out.println("(] is valid: " + matcher.isValid("(]"));         // false
        System.out.println("({[ is valid: " + matcher.isValid("({["));       // false
        System.out.println("}} is valid: " + matcher.isValid("}}"));         // false
        System.out.println(" is valid: " + matcher.isValid(""));             // true
    }
}
登录后复制

除了括号匹配,Java栈还有哪些典型应用场景?

除了括号匹配,栈在Java编程中扮演着多面手的角色。我个人觉得,最直观的莫过于它在计算机底层,特别是JVM中对函数调用的管理。每次方法调用,参数、局部变量、返回地址都会被压入一个“栈帧”中,方法执行完毕,栈帧弹出,这简直是LIFO的最佳写照。再比如,表达式求值,无论是将中缀表达式转换为后缀或前缀,还是直接计算后缀表达式,栈都能大显身手。还有那些我们日常离不开的“撤销/重做”功能,浏览器的前进/后退历史,甚至是图或树的深度优先遍历(DFS),栈都是其核心支撑结构。它提供了一种天然的顺序性,让那些需要反向处理或临时存储的逻辑变得清晰而高效。

如何在Java中实现一个基于栈的表达式求值器?

要说栈的实际应用,一个简单的后缀表达式求值器是个不错的例子。我们知道,后缀表达式(逆波兰表示法)的优点在于不需要括号就能明确运算顺序,非常适合用栈来处理。

代码小浣熊
代码小浣熊

代码小浣熊是基于商汤大语言模型的软件智能研发助手,覆盖软件需求分析、架构设计、代码编写、软件测试等环节

代码小浣熊 51
查看详情 代码小浣熊

其核心逻辑是:

  1. 遍历后缀表达式的每个元素。
  2. 如果是数字,就直接压入栈中。
  3. 如果是运算符,就从栈中弹出两个操作数(注意顺序,先弹出的通常是第二个操作数),执行运算,然后将结果再压回栈中。
  4. 表达式遍历完毕,栈中剩下的唯一元素就是最终结果。

这种模式非常简洁,避免了处理操作符优先级和括号的复杂性。

import java.util.ArrayDeque;
import java.util.Deque;

public class PostfixEvaluator {

    public int evaluate(String expression) {
        Deque<Integer> stack = new ArrayDeque<>();
        String[] tokens = expression.split(" "); // 假设数字和运算符用空格分隔

        for (String token : tokens) {
            if (token.matches("-?\d+")) { // 如果是数字(包括负数)
                stack.push(Integer.parseInt(token));
            } else { // 如果是运算符
                if (stack.size() < 2) {
                    throw new IllegalArgumentException("Invalid postfix expression: not enough operands for operator " + token);
                }
                int operand2 = stack.pop(); // 先弹出的作为第二个操作数
                int operand1 = stack.pop(); // 后弹出的作为第一个操作数
                int result;
                switch (token) {
                    case "+":
                        result = operand1 + operand2;
                        break;
                    case "-":
                        result = operand1 - operand2;
                        break;
                    case "*":
                        result = operand1 * operand2;
                        break;
                    case "/":
                        if (operand2 == 0) {
                            throw new ArithmeticException("Division by zero");
                        }
                        result = operand1 / operand2;
                        break;
                    default:
                        throw new IllegalArgumentException("Unknown operator: " + token);
                }
                stack.push(result);
            }
        }

        if (stack.size() != 1) {
            throw new IllegalArgumentException("Invalid postfix expression: too many operands or malformed");
        }
        return stack.pop();
    }

    public static void main(String[] args) {
        PostfixEvaluator evaluator = new PostfixEvaluator();
        System.out.println("3 4 + 5 * = " + evaluator.evaluate("3 4 + 5 *")); // (3+4)*5 = 35
        System.out.println("10 2 / = " + evaluator.evaluate("10 2 /"));     // 10/2 = 5
        System.out.println("5 1 2 + 4 * + 3 - = " + evaluator.evaluate("5 1 2 + 4 * + 3 -")); // 5 + ((1+2)*4) - 3 = 5 + 12 - 3 = 14
    }
}
登录后复制

使用Java栈时常见的陷阱与优化建议有哪些?

在Java里用栈,虽然概念简单,但有些地方还是得留心。

首先,我个人总是推荐用

java.util.Deque
登录后复制
接口的实现,比如
ArrayDeque
登录后复制
LinkedList
登录后复制
,来作为栈使用,而不是直接用
java.util.Stack
登录后复制
这个老旧的类。
Stack
登录后复制
Vector
登录后复制
的子类,继承了同步开销,而且API设计上有些不那么直观。
Deque
登录后复制
作为双端队列,提供了
push()
登录后复制
pop()
登录后复制
peek()
登录后复制
这些符合栈语义的方法,效率更高,也更符合现代Java的编程习惯。

其次,栈溢出(Stack Overflow)是个经典的错误。这通常不是数据结构本身的问题,而是指方法调用栈溢出,比如无限递归。虽然和我们这里讨论的数据结构栈是两回事,但在实际编程中,如果你的算法设计导致递归深度过大,或者在栈上分配了过多的局部变量,都可能触发这个错误。

再者,多线程环境下,如果你需要一个线程安全的栈,

Stack
登录后复制
类是同步的,但通常我们更倾向于使用
Collections.synchronizedList(new LinkedList<>())
登录后复制
ConcurrentLinkedDeque
登录后复制
等并发集合,它们提供了更细粒度的控制或更好的并发性能。如果不需要线程安全,
ArrayDeque
登录后复制
无疑是最佳选择。

最后,也是最基础的,任何时候对栈进行

pop()
登录后复制
peek()
登录后复制
操作之前,务必检查栈是否为空。否则,一个
EmptyStackException
登录后复制
就可能让你的程序崩溃。这些看似琐碎的细节,往往决定了代码的健壮性。

以上就是java代码怎样实现栈的括号匹配功能 java代码栈应用场景的实现方法​的详细内容,更多请关注php中文网其它相关文章!

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号