日撸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 开发者大会开幕 锁定大会官网观看主旨演讲现场直播! 本次大会内容将同步于多个…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
