当前位置: 首页 > news >正文

日撸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.完整的程序代码 总结 一、栈的括号匹配 要完成今天的任务&#xff0c;需要先来了解一下什么是栈的括号匹配。首先&#xff0c;顾名思义&#xff0c;括号匹配就是指将一对括号匹配起来&#xff0c;我们给定一…...

Oracle-OracleConnector

提示&#xff1a;OracleConnector 类是 Debezium 中用于与 Oracle 数据库交互的一个连接器组件 文章目录 前言一、核心功能二、代码分析总结 前言 提示&#xff1a;OracleConnector 类负责配置、启动、管理和验证与 Oracle 数据库的连接&#xff0c;并为后续的数据捕获任务准备…...

『 Linux 』线程池与 POSIX 线程的封装编码实现

文章目录 线程池概念线程池的编码实现线程池的测试参考代码 线程的封装使用测试封装后的线程参考代码 线程池概念 池化技术是一种资源管理方法,通过预先创建和管理一组资源以便在需要使用时快速分配这些资源; 线程池是池化技术的一种典型应用; 资源分配 在线程池中预先创建一定…...

【C++】————哈希表

作者主页&#xff1a; 作者主页 本篇博客专栏&#xff1a;C 创作时间 &#xff1a;2024年8月6日 前言&#xff1a; 在计算机科学的广袤世界中&#xff0c;数据结构犹如基石&#xff0c;支撑着各种高效算法的构建与运行。而哈希表&#xff08;Hash Table&#xff09;&#…...

前端学习AI历程

AI基本概念tensorflow入门conda搭建环境&#xff0c;pycham使用训练自己的第一个模型AI目前前端方便入手的几个方向 素材图片库图像识别&#xff0c;在线学习低代码应用智能客服 获取数据集 roboflowkagglecocomakesense&#xff08;用于打标&#xff09; 认识yolo两个简单小应…...

常见中间件漏洞复现之【Tomcat】!

Tomcat介绍 tomcat是⼀个开源⽽且免费的jsp服务器&#xff0c;默认端⼝ : 8080&#xff0c;属于轻量级应⽤服务器。它可以实现 JavaWeb程序的装载&#xff0c;是配置JSP&#xff08;Java Server Page&#xff09;和JAVA系统必备的⼀款环境。 在历史上也披露出来了很多的漏洞 …...

C++并发编程(一):线程基础

简介 本文学习的是 b 站 up 恋恋风辰的并发编程教学视频做的一些笔记补充。 教程视频链接如下&#xff1a;线程基础&#xff1a;视频教程 文档链接如下&#xff1a;线程基础&#xff1a;笔记文档 理论上直接看 up 提供的笔记文档即可&#xff0c;我这里主要是记录一些我自己…...

enq: HW - contention事件来啦

业务系统反应数据库慢&#xff0c;根据时间查看awr报告。 先看一眼事件名称 HW enqueue 用于序列化超出段高水位线的空间分配。如果同时向对象添加大量数据&#xff0c;则多个进程可能同时尝试在高水位线上方分配空间&#xff0c;从而导致争用。 既然是控制资源并发的enq&…...

MyBatis补充

控制类和dao层接口以及mapper中的xml是怎样的关联的&#xff1f; 在Mybatis中&#xff0c;控制类和dao层接口是通过mapper的xml文件进行连接的。 控制类调用dao层接口中的方法&#xff0c;通过接口实现进行访问数据库操作。dao层接口定义数据库操作的方法&#xff0c;提供给控制…...

系统架构师(每日一练16)

每日一练 答案与解析 1.软件测试一般分为两个大类:动态测试和静态测试。前者通过运行程序发现错误&#xff0c;包括()等方法;后者采用人工和计算机辅助静态分析的手段对程序进行检测&#xff0c;包括()等方法。答案与解析 问题1 A.边界值分析、逻辑覆盖、基本路径 B.桌面检查、…...

实践致知第17享:电脑忽然黑屏的常见原因及处理方法

一、背景需求 小姑电话说&#xff1a;最近&#xff0c;电脑忽然就黑屏了&#xff08;如下图所示&#xff09;&#xff0c;但是等待几十秒甚至一分钟&#xff0c;电脑就能自然恢复了&#xff0c;这种状况一天能出现三四次&#xff0c;怎么办&#xff1f; 二、分析诊断 电脑黑屏…...

微信小程序--实现地图定位---获取经纬度

(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()` 函数

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

【多模态大模型】 BLIP-2 in ICML 2023

一、引言 论文&#xff1a; BLIP-2: Bootstrapping Language-Image Pre-training with Frozen Image Encoders and Large Language Models 作者&#xff1a; Salesforce Research 代码&#xff1a; BLIP-2 特点&#xff1a; 该方法分别使用冻结的图像编码器&#xff08;ViT-L/…...

HPC高性能计算平台

随着技术的发展和数据量的爆炸性增长&#xff0c;企业面临的挑战日益复杂&#xff0c;对计算能力的需求也在不断增加。这些问题的解决超出了传统计算方法的能力范围&#xff0c;高性能计算&#xff08;HPC&#xff09;正是为解决这类问题而生。 高性能计算&#xff08;HPC&…...

前端常用的几个工具网站

觉得不错的前端工具类网站 1、Grid布局生成 https://cssgrid-generator.netlify.app 2、拟物按钮样式生成 https://neumorphism.io 3、玻璃形态效果 在线制作CSS玻璃形态 4、一些Button、checkBox、switch、card的css样式 零代码 - 精美CSS样式库 5、CSS阴影生成 在线创建…...

支付功能之代收代付

有很多老板问小编&#xff1a;“这个分账功能好是好&#xff0c;也能搞定项目中的二清问题和税务纠纷&#xff0c;但还是太复杂了&#xff0c;每次要添加被分账对象都需要提交材料进行审核&#xff0c;太繁琐了&#xff0c;有没有更方便快捷的支付产品来解决资金问题&#xff1…...

QPixmap

pixel[ˈpɪksl]像素 QPixmap 是 Qt 框架中用于处理图像的一个类。它主要用于在屏幕上显示和处理图像&#xff0c;提供了许多实用的功能&#xff0c;如加载、保存、缩放、旋转、合并等。 绘制 从文件加载&#xff1a;从指定文件加载图像。 QPixmap pixmap(":/images/exam…...

Laravel门面之下:构建自定义门面应用的艺术

Laravel门面之下&#xff1a;构建自定义门面应用的艺术 在Laravel框架中&#xff0c;门面&#xff08;Facade&#xff09;提供了一种将类静态调用与面向对象代码解耦的优雅方式。门面是一个全局可访问的类&#xff0c;它为底层复杂的服务提供了一个简单的接口。然而&#xff0…...

智启万象 | 2024 Google 开发者大会直播攻略

8 月 7 日上午 9:30 2024 Google 开发者大会 主旨演讲直播将准时开启 想要在线上探索大会精彩内容&#xff1f; 快查收这份观看指南&#xff01; 8 月 7 日上午 9:30 2024 Google 开发者大会开幕 锁定大会官网观看主旨演讲现场直播&#xff01; 本次大会内容将同步于多个…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

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…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; 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操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...