日撸Java三百行(day15:栈的应用之括号匹配)
目录
一、栈的括号匹配
二、代码实现
1.方法创建
2.数据测试
3.完整的程序代码
总结
一、栈的括号匹配
要完成今天的任务,需要先来了解一下什么是栈的括号匹配。首先,顾名思义,括号匹配就是指将一对括号匹配起来,我们给定一个字符串(字符串中除了各类括号,也可以有别的字符),将字符串中的所有括号都根据规则:对应的一对左括号与右括号按“先左后右”的顺序匹配起来,这个过程即为括号匹配。
在判断括号匹配时,需要注意一些细节:
- 必须是对应的一对左括号与右括号,即“( ”与“ )”对应,“ [ ”与“ ] ”对应,“ { ”与“ } ”对应。
- 必须是“一左一右”,不能两个均为左括号或者两个均为右括号,即“( ”与“ )”可以匹配,但是“( ”与“( ”不匹配,“ )”与“ )”也不匹配。
- 必须按“先左后右”的顺序,即“( )”匹配,但是“ )( ”就不匹配。
- 括号匹配遵循就近原则,以当前括号的左边第一个括号为准。比如在下面的字符串中,设第6个括号为当前括号,那么就以该括号左边第一个括号为准,即以第5个括号为准,所以5、6成功匹配。可以看到,在下图中第6个括号与第3个括号也满足了以上三个基本条件,但是因为就近原则的存在,所以3、6不匹配。同理,如果第5个括号改为了“ [ ”或者“ { ”,那么5、6也不会匹配。

- 括号匹配遵循匹配消除原则,一旦某一对括号匹配成功,那么该对括号就“消除”,继续匹配后面的括号。比如在上图中,5、6成功匹配后“消除”,然后4、7继续匹配,再比如“ { [ ( ) ] } ”也是匹配的。
- 所给字符串中的全部括号都匹配成功才算完成了括号匹配,比如“ [ { ( [ ( ) ] ) } ] ”是匹配的,但是“ ( [ { ( [ ] ) ] ] ) ”就不匹配。
- 在所给的字符串中,除了各类括号,也可以有别的字符,比如“ 10 / { [ 4 - ( 5 - 2 ) ] * 2 } ”也是匹配的。
二、代码实现
弄清楚基本概念后,就可以进行代码实现了。根据“先左后右”的顺序要求以及匹配消除原则,我们可以按如下步骤进行括号匹配(因为别的非括号字符对于括号匹配不起任何作用,所以直接视为透明就行):
- 遇到左括号“( ”、“ [ ”、“ { ”就直接入栈,在栈中存放
- 遇到右括号“ )”、“ ] ”、“ } ”就从栈中弹出栈顶元素,与该右括号进行匹配,如果二者匹配成功就“消除”,继续匹配后面的括号;如果二者匹配不成功,直接输出不匹配即可
不过,需要注意一点,由于要求的是字符串中的全部括号均匹配才算成功,所以如果匹配完毕后发现栈中仍然还存在左括号或者栈不空,那么也算作匹配失败。
对于这个问题,我们当然可以选择在匹配完毕后直接判断栈是否为空,但是我们也可以采取另一种方式:即在进行括号匹配之前,入栈一个非括号字符作为栈底元素,再在匹配完毕后进行出栈操作,判断此时出栈的元素是否为该非括号字符,如果是,则说明字符串中的全部括号均已匹配;如果不是,则直接返回不匹配。
1.方法创建
进行代码模拟时,我们只需要在昨天的代码基础上增加一个括号匹配的方法即可,如下:
/************************ Is the bracket matching?* * @param paraString The given expression.* @return Match or not.**********************/public static boolean bracketMatching(String paraString) {// Step 1. Initialize the stack through pushing a '#' at the bottom.CharStack tempStack = new CharStack();tempStack.push('#');char tempChar, tempPoppedChar;// Step 2. Process the string. For a string, length() is a method// instead of a member variable.for(int i = 0; i < paraString.length(); i++) {tempChar = paraString.charAt(i);switch(tempChar) {case '(':case '[':case '{':tempStack.push(tempChar);break;case ')':tempPoppedChar = tempStack.pop();if(tempPoppedChar != '(') {return false;} // of ifbreak;case ']':tempPoppedChar = tempStack.pop();if(tempPoppedChar != '[') {return false;} // of ifbreak;case '}':tempPoppedChar = tempStack.pop();if(tempPoppedChar != '{') {return false;} // of ifbreak;default:// Do nothing} // of switch} // of for itempPoppedChar = tempStack.pop();if(tempPoppedChar != '#') {return false;} // of ifreturn true;} // of bracketMatching
首先,定义括号匹配的方法bracketMatching,其中String类型的参数paraString即为要输入的字符串,再创建一个栈,并入栈一个'#',将'#' 作为栈底的非括号字符。
然后,利用charAt()方法+for循环,将字符串中的字符一个一个读取出来。
补充:
length()方法:作用是返回字符串的长度,调用格式为字符串名.length()
charAt()方法:作用是获取字符串中指定索引值的字符,调用格式为字符串名.charAt(指定索引值)
根据之前的分析,这里需要进行读取字符的判断,且判断分支较多,符合switch语句适用的情况(单一变量的多个不同取值问题),所以我们采用了switch语句。
匹配完毕后,进行出栈操作,并判断此时出栈的元素是否为'#',如果不是则直接返回false;如果是,则返回true。
2.数据测试
下面我们进行数据测试,这里用到了以下五个数据:
- [ 2 + (1 - 3) ] * 4
- ( ) )
- ( ) ( ) ( ( ) )
- ( { } [ ] )
- ) (
显然,通过直接思考可以预测第1、3、4个字符串是匹配的,剩下的是不匹配的。
/************************The entrance of the program.** @param args Not used now.**********************/public static void main(String[] args) {CharStack tempStack = new CharStack();for(char ch = 'a'; ch < 'm'; ch++) {tempStack.push(ch);System.out.println("The current stack is: " + tempStack);} // of for chchar tempChar;for(int i = 0; i < 12; i++) {tempChar = tempStack.pop();System.out.println("Popped: " + tempChar);System.out.println("The current stack is: " + tempStack);} // of for iboolean tempMatch;String tempExpression = "[2 + (1 - 3)] * 4";tempMatch = bracketMatching(tempExpression);System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);tempExpression = "( ) )";tempMatch = bracketMatching(tempExpression);System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);tempExpression = "()()(())";tempMatch = bracketMatching(tempExpression);System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);tempExpression = "({}[])";tempMatch = bracketMatching(tempExpression);System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);tempExpression = ")(";tempMatch = bracketMatching(tempExpression);System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);} // of main
3.完整的程序代码
package datastructure;/***Char stack. I do not use Stack because it is already defined in Java.**@auther Xin Lin 3101540094@qq.com.*/public class CharStack {/*** The depth.*/public static final int MAX_DEPTH = 10;/*** The actual depth.*/int depth;/*** The data.*/char[] data;/************************ Construct an empty char stack.**********************/public CharStack() {depth = 0;data = new char[MAX_DEPTH];} // of the first constructor/************************ Overrides the method claimed in Object, the superclass of any class.**********************/public String toString() {String resultString = "";for (int i = 0; i < depth; i++) {resultString += data[i];} // of for ireturn resultString;} // of toString/************************ Push an element.* * @param paraChar The given char.* @return Success or not.**********************/public boolean push(char paraChar) {if (depth == MAX_DEPTH) {System.out.println("Stack full.");return false;} // of ifdata[depth] = paraChar;depth++;return true;} // of push/************************ Pop an element.* * @return The popped char.**********************/public char pop() {if(depth == 0) {System.out.println("Nothing to pop.");return '\0';} // of ifchar resultChar = data[depth - 1];depth--;return resultChar;} // of pop/************************ Is the bracket matching?* * @param paraString The given expression.* @return Match or not.**********************/public static boolean bracketMatching(String paraString) {// Step 1. Initialize the stack through pushing a '#' at the bottom.CharStack tempStack = new CharStack();tempStack.push('#');char tempChar, tempPoppedChar;// Step 2. Process the string. For a string, length() is a method// instead of a member variable.for(int i = 0; i < paraString.length(); i++) {tempChar = paraString.charAt(i);switch(tempChar) {case '(':case '[':case '{':tempStack.push(tempChar);break;case ')':tempPoppedChar = tempStack.pop();if(tempPoppedChar != '(') {return false;} // of ifbreak;case ']':tempPoppedChar = tempStack.pop();if(tempPoppedChar != '[') {return false;} // of ifbreak;case '}':tempPoppedChar = tempStack.pop();if(tempPoppedChar != '{') {return false;} // of ifbreak;default:// Do nothing} // of switch} // of for itempPoppedChar = tempStack.pop();if(tempPoppedChar != '#') {return false;} // of ifreturn true;} // of bracketMatching/************************The entrance of the program.** @param args Not used now.**********************/public static void main(String[] args) {CharStack tempStack = new CharStack();for(char ch = 'a'; ch < 'm'; ch++) {tempStack.push(ch);System.out.println("The current stack is: " + tempStack);} // of for chchar tempChar;for(int i = 0; i < 12; i++) {tempChar = tempStack.pop();System.out.println("Popped: " + tempChar);System.out.println("The current stack is: " + tempStack);} // of for iboolean tempMatch;String tempExpression = "[2 + (1 - 3)] * 4";tempMatch = bracketMatching(tempExpression);System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);tempExpression = "( ) )";tempMatch = bracketMatching(tempExpression);System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);tempExpression = "()()(())";tempMatch = bracketMatching(tempExpression);System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);tempExpression = "({}[])";tempMatch = bracketMatching(tempExpression);System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);tempExpression = ")(";tempMatch = bracketMatching(tempExpression);System.out.println("Is the expression " + tempExpression + " bracket matching? " + tempMatch);} // of main
} // of class CharStack
运行结果:

可以发现运行结果与我们之前的预测是完全相同的。
总结
总体来说,今天学习的内容不是很复杂,简单来说就是对昨天栈的入栈出栈等操作进行一个应用,而且根据今天代码的难度,其实可以知道括号匹配算是栈的一个基本应用,不过它也是一个非常重要的应用,在今后很多算法和问题中都会涉及到。
相关文章:
日撸Java三百行(day15:栈的应用之括号匹配)
目录 一、栈的括号匹配 二、代码实现 1.方法创建 2.数据测试 3.完整的程序代码 总结 一、栈的括号匹配 要完成今天的任务,需要先来了解一下什么是栈的括号匹配。首先,顾名思义,括号匹配就是指将一对括号匹配起来,我们给定一…...
Oracle-OracleConnector
提示:OracleConnector 类是 Debezium 中用于与 Oracle 数据库交互的一个连接器组件 文章目录 前言一、核心功能二、代码分析总结 前言 提示:OracleConnector 类负责配置、启动、管理和验证与 Oracle 数据库的连接,并为后续的数据捕获任务准备…...
『 Linux 』线程池与 POSIX 线程的封装编码实现
文章目录 线程池概念线程池的编码实现线程池的测试参考代码 线程的封装使用测试封装后的线程参考代码 线程池概念 池化技术是一种资源管理方法,通过预先创建和管理一组资源以便在需要使用时快速分配这些资源; 线程池是池化技术的一种典型应用; 资源分配 在线程池中预先创建一定…...
【C++】————哈希表
作者主页: 作者主页 本篇博客专栏:C 创作时间 :2024年8月6日 前言: 在计算机科学的广袤世界中,数据结构犹如基石,支撑着各种高效算法的构建与运行。而哈希表(Hash Table)&#…...
前端学习AI历程
AI基本概念tensorflow入门conda搭建环境,pycham使用训练自己的第一个模型AI目前前端方便入手的几个方向 素材图片库图像识别,在线学习低代码应用智能客服 获取数据集 roboflowkagglecocomakesense(用于打标) 认识yolo两个简单小应…...
常见中间件漏洞复现之【Tomcat】!
Tomcat介绍 tomcat是⼀个开源⽽且免费的jsp服务器,默认端⼝ : 8080,属于轻量级应⽤服务器。它可以实现 JavaWeb程序的装载,是配置JSP(Java Server Page)和JAVA系统必备的⼀款环境。 在历史上也披露出来了很多的漏洞 …...
C++并发编程(一):线程基础
简介 本文学习的是 b 站 up 恋恋风辰的并发编程教学视频做的一些笔记补充。 教程视频链接如下:线程基础:视频教程 文档链接如下:线程基础:笔记文档 理论上直接看 up 提供的笔记文档即可,我这里主要是记录一些我自己…...
enq: HW - contention事件来啦
业务系统反应数据库慢,根据时间查看awr报告。 先看一眼事件名称 HW enqueue 用于序列化超出段高水位线的空间分配。如果同时向对象添加大量数据,则多个进程可能同时尝试在高水位线上方分配空间,从而导致争用。 既然是控制资源并发的enq&…...
MyBatis补充
控制类和dao层接口以及mapper中的xml是怎样的关联的? 在Mybatis中,控制类和dao层接口是通过mapper的xml文件进行连接的。 控制类调用dao层接口中的方法,通过接口实现进行访问数据库操作。dao层接口定义数据库操作的方法,提供给控制…...
系统架构师(每日一练16)
每日一练 答案与解析 1.软件测试一般分为两个大类:动态测试和静态测试。前者通过运行程序发现错误,包括()等方法;后者采用人工和计算机辅助静态分析的手段对程序进行检测,包括()等方法。答案与解析 问题1 A.边界值分析、逻辑覆盖、基本路径 B.桌面检查、…...
实践致知第17享:电脑忽然黑屏的常见原因及处理方法
一、背景需求 小姑电话说:最近,电脑忽然就黑屏了(如下图所示),但是等待几十秒甚至一分钟,电脑就能自然恢复了,这种状况一天能出现三四次,怎么办? 二、分析诊断 电脑黑屏…...
微信小程序--实现地图定位---获取经纬度
(1) (2) (3) html: <view class"titleTwo" style"border: none;"><view class"fontSize30 invoiceTile">企业地址</view><view class"invoiceRight" bind:tap"tapChooseAddress" data-maptype"…...
【Python系列】使用 `isinstance()` 替代 `type()` 函数
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
【多模态大模型】 BLIP-2 in ICML 2023
一、引言 论文: BLIP-2: Bootstrapping Language-Image Pre-training with Frozen Image Encoders and Large Language Models 作者: Salesforce Research 代码: BLIP-2 特点: 该方法分别使用冻结的图像编码器(ViT-L/…...
HPC高性能计算平台
随着技术的发展和数据量的爆炸性增长,企业面临的挑战日益复杂,对计算能力的需求也在不断增加。这些问题的解决超出了传统计算方法的能力范围,高性能计算(HPC)正是为解决这类问题而生。 高性能计算(HPC&…...
前端常用的几个工具网站
觉得不错的前端工具类网站 1、Grid布局生成 https://cssgrid-generator.netlify.app 2、拟物按钮样式生成 https://neumorphism.io 3、玻璃形态效果 在线制作CSS玻璃形态 4、一些Button、checkBox、switch、card的css样式 零代码 - 精美CSS样式库 5、CSS阴影生成 在线创建…...
支付功能之代收代付
有很多老板问小编:“这个分账功能好是好,也能搞定项目中的二清问题和税务纠纷,但还是太复杂了,每次要添加被分账对象都需要提交材料进行审核,太繁琐了,有没有更方便快捷的支付产品来解决资金问题࿱…...
QPixmap
pixel[ˈpɪksl]像素 QPixmap 是 Qt 框架中用于处理图像的一个类。它主要用于在屏幕上显示和处理图像,提供了许多实用的功能,如加载、保存、缩放、旋转、合并等。 绘制 从文件加载:从指定文件加载图像。 QPixmap pixmap(":/images/exam…...
Laravel门面之下:构建自定义门面应用的艺术
Laravel门面之下:构建自定义门面应用的艺术 在Laravel框架中,门面(Facade)提供了一种将类静态调用与面向对象代码解耦的优雅方式。门面是一个全局可访问的类,它为底层复杂的服务提供了一个简单的接口。然而࿰…...
智启万象 | 2024 Google 开发者大会直播攻略
8 月 7 日上午 9:30 2024 Google 开发者大会 主旨演讲直播将准时开启 想要在线上探索大会精彩内容? 快查收这份观看指南! 8 月 7 日上午 9:30 2024 Google 开发者大会开幕 锁定大会官网观看主旨演讲现场直播! 本次大会内容将同步于多个…...
2026年软件测试十大趋势预测:AI将重塑一切?
站在质效革命的十字路口当软件从静态工具进化为驱动社会运转的智能神经中枢,其复杂性与不确定性呈指数级增长。传统质量保障体系正经历系统性重构,AI的深度渗透、开发范式的升维以及业务对极致体验的追求,共同推动软件测试迈入“质效革命”新…...
【11月16日-大模型前置知识【深度学习】+大模型开发入门】-基础篇笔记
文章目录前言一、huggingface国内1.引入库2.LLM 大模型语言的基础知识:2.LLM主要类别架构介绍3.卷积神经网络CNN4.循环神经网络总结全文通俗总结一、入门工具:Hugging Face二、LLM底层核心:语言模型的进化三、主流LLM架构大盘点四、深度学习基…...
《算法题讲解指南:动态规划算法--回文串问题》--35.回文子串,36. 最长回文子串,37.分割回文串 IV,38.分割回文串 II,39.最长回文子序列,40.让字符串成为回文串的最少插入次数
🔥小叶-duck:个人主页 ❄️个人专栏:《Data-Structure-Learning》《C入门到进阶&自我学习过程记录》 《算法题讲解指南》--优选算法 《算法题讲解指南》--递归、搜索与回溯算法 《算法题讲解指南》--动态规划算法 ✨未择之路࿰…...
2026年佛山GEO优化公司哪家好?推荐评测口碑对比知名七家排名
随着生成式AI全面渗透商业决策,企业获取客户的核心入口正从传统搜索转向豆包、DeepSeek等AI助手。中国互联网络信息中心发布的行业报告显示,生成式AI用户规模持续高速增长,这直接催生了生成引擎优化这一全新营销赛道。品牌能否在AI的答案中被…...
C#联合halcon开发框架源码。 拖拽式编程,无halcon基础也能上手,匹配,测量,条码识...
C#联合halcon开发框架源码。 拖拽式编程,无halcon基础也能上手,匹配,测量,条码识别,ocr,定位引导,对位等,支持plc通讯,集成主流相机sdk,系统集成. 最近在工业视觉项目里折腾Halcon的时候&#x…...
Cadence 17.2 allegro怎么把线从中间剪掉一段
可以点Delete命令右键选cut剪切,在点线的要剪切的开始点和结束点。1、减掉一段丝印线右键-->cut选中要裁剪的线的开始点和结束点,右键done2、减掉一段导线右键-->cut选中要裁剪的线的开始点和结束点,右键done。...
AI治理窗口期只剩11个月?2026奇点大会倒计时预警:欧盟AI Act 2.0、中国《生成式AI服务安全评估指南》与NIST AI RMF 2.1三轨并行下的最后合规冲刺清单
第一章:2026奇点智能技术大会:AI原生安全治理 2026奇点智能技术大会(https://ml-summit.org) AI原生安全治理的核心范式转变 传统安全治理模型正面临根本性挑战:模型权重泄露、提示注入绕过、推理时侧信道攻击、训练数据残留隐私泄露等问题…...
Python 3D游戏开发实战:Ursina引擎从入门到精通
1. 为什么选择Ursina引擎开发3D游戏 如果你正在寻找一个简单易用的Python 3D游戏引擎,Ursina绝对值得一试。作为一个基于Panda3D的轻量级封装,Ursina让3D游戏开发变得前所未有的简单。我最初接触它时,就被它简洁的API设计所吸引——用不到10行…...
掌握AI教材写作,借助低查重方法打造优质专业教材!
教材创作难题与AI解决方案 很多教材编写者都会遇到一个共同的问题:虽然他们的正文内容经过了精细的打磨,但由于配套资源的缺乏,整体教学效果受到影响。设计不同层次的课后练习往往需要新颖的点子,而很多时候这些灵感难以涌现&…...
实时行情系统设计:从协议选择到高可用架构,再到数据源选型泵
一、核心问题及解决方案(按踩坑频率排序) 问题 1:误删他人持有锁——最基础也最易犯的漏洞 成因:释放锁时未做身份校验,直接执行 DEL 命令删除键。典型场景:服务 A 持有锁后,业务逻辑耗时超过锁…...
