日撸Java三百行(day15:栈的应用之括号匹配)

news2024/11/24 5:02:01

目录

一、栈的括号匹配

二、代码实现

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 if
				break;
			case ']':
				tempPoppedChar = tempStack.pop();
				if(tempPoppedChar != '[') {
					return false;
				} // of if
				break;
			case '}':
				tempPoppedChar = tempStack.pop();
				if(tempPoppedChar != '{') {
					return false;
				} // of if
				break;
			default:
				// Do nothing
			} // of switch
		} // of for i
		
		tempPoppedChar = tempStack.pop();
		if(tempPoppedChar != '#') {
			return false;
		} // of if
		
		return 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 ch
		
		char 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 i
		
		boolean 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 i
		
		return 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 if
		
		data[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 if
		
		char 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 if
				break;
			case ']':
				tempPoppedChar = tempStack.pop();
				if(tempPoppedChar != '[') {
					return false;
				} // of if
				break;
			case '}':
				tempPoppedChar = tempStack.pop();
				if(tempPoppedChar != '{') {
					return false;
				} // of if
				break;
			default:
				// Do nothing
			} // of switch
		} // of for i
		
		tempPoppedChar = tempStack.pop();
		if(tempPoppedChar != '#') {
			return false;
		} // of if
		
		return 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 ch
		
		char 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 i
		
		boolean 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

运行结果:

可以发现运行结果与我们之前的预测是完全相同的。 

总结

总体来说,今天学习的内容不是很复杂,简单来说就是对昨天栈的入栈出栈等操作进行一个应用,而且根据今天代码的难度,其实可以知道括号匹配算是栈的一个基本应用,不过它也是一个非常重要的应用,在今后很多算法和问题中都会涉及到。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1986595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HashTable源码

引子 看到一个关于HashMap和HashTable对比的面试题&#xff0c;于是简单看了下HashTable的源码&#xff0c;简单记录下。 概述 与HashMap相似的哈希表结构&#xff0c;有很多不同点&#xff1a; 节点数组的初始化是在构造函数中完成的&#xff0c;初始容量11&#xff0c;负载因…

基于JSP、java、Tomcat三者的项目实战--校园交易网(3)主页--历史清单

技术支持&#xff1a;JAVA、JSP 服务器&#xff1a;TOMCAT 7.0.86 编程软件&#xff1a;IntelliJ IDEA 2021.1.3 x64 前文几个功能的实现的博客 基于JSP、java、Tomcat、mysql三层交互的项目实战--校园交易网&#xff08;1&#xff09;-项目搭建&#xff08;前期准备工作&a…

工具学习_CVE Binary Tool

1. 工具概述 CVE Binary Tool 是一个免费的开源工具&#xff0c;可帮助您使用国家漏洞数据库&#xff08;NVD&#xff09;常见漏洞和暴露&#xff08;CVE&#xff09;列表中的数据以及Redhat、开源漏洞数据库&#xff08;OSV&#xff09;、Gitlab咨询数据库&#xff08;GAD&am…

鸿蒙AI功能开发【人脸活体验证控件】 机器学习-场景化视觉服务

人脸活体验证控件 介绍 本示例展示了使用视觉类AI能力中的人脸活体验证能力。 本示例模拟了在应用里&#xff0c;跳转人脸活体验证控件&#xff0c;获取到验证结果并展示出来。 需要使用hiai引擎框架人脸活体验证接口kit.VisionKit.d.ts。 效果预览 使用说明&#xff1a; …

RK3568平台开发系列讲解(文件系统篇)文件描述符 fd(File Descriptor)是什么?

📢USB控制传输是USB通信中的一种基本传输类型,用于控制USB设备的配置和操作。它由 Setup 阶段和 Data 阶段组成,可用于发送命令、读取状态、配置设备等操作。 一、文件描述符 fd(File Descriptor)是什么? 文件描述符 fd 是一个非负整数,用来标识一个打开的文件,由内核…

用户态tcp协议栈四次挥手-服务端发送fin时,客户端不返回ac

问题&#xff1a; 四次挥手时&#xff0c;服务端发送fin后&#xff0c;客户端不发送ack&#xff0c;反而过了2min后发了个rst报文 62505是客户端&#xff0c;8889是服务端 解决&#xff1a; 服务端返回fin报文时带上ack标记

微波武器反无人机技术详解

微波武器反无人机技术中展现出了独特的优势和广阔的应用前景。以下是对微波武器在反无人机技术方面的详细解析&#xff1a; 一、微波武器概述 微波武器是指配备高功率微波&#xff08;High-Power Microwave, HPM&#xff09;载荷的作战武器&#xff0c;能够发射高能量的电磁脉…

在AI浪潮中保持核心竞争力:XIAOJUSURVEY的智能化探索

讲点实在的 在AI技术快速发展的今天&#xff0c;各行各业的工作方式正经历深刻变革。尤其是身处浪潮中甚至最有机会推动发展的我们&#xff0c;更需要置身事内。 ChatGPT、Copilot等的普及&#xff0c;使得编程效率显著提升&#xff0c;但也带来了新的挑战。为了在这种变革中…

C++输出为非科学计数法不同数据类型表示范围

目录 一、C数据类型 1、基本的内置类型 2、修饰符 &#xff08;1&#xff09;signed 和 unsigned &#xff08;2&#xff09;short 和 long &#xff08;3&#xff09;区别总结 默认情况 二、类型转换 1、静态转换&#xff08;Static Cast&#xff09; 2、动态转换&a…

C语言——函数(1)

函数 定义&#xff1a; 函数就是用来完成一定功能的一段代码&#xff08;程序&#xff09;模块。 在设计较大的程序时&#xff0c;一般将其分为若干个程序模块&#xff0c;每个模块用来实现一定的功能。 函数优势&#xff1a; 我们可以通过函数提供功能给别人使用&#xff0c…

美国商超入驻Homedepot,传统家织厂家跨境赛道新选择?——WAYLI威利跨境助力商家

美国商超入驻Homedepot为传统家织厂家提供了新跨境选择。据《Interactive Home Shopping》一文&#xff0c;电子购物让消费者更易定位和比较产品。传统家织厂家可通过Homedepot等大型零售商&#xff0c;利用其平台优势&#xff0c;接触更广泛消费者。 根据《Homedepot之争——家…

【八股文】Redis

1.Redis有哪些数据类型 常用的数据类型&#xff0c;String&#xff0c;List&#xff0c;Set&#xff0c;Hash和ZSet&#xff08;有序&#xff09; String&#xff1a;Session&#xff0c;Token&#xff0c;序列化后的对象存储&#xff0c;BitMap也是用的String类型&#xff0c;…

案例:LVS+Keepalived集群

目录 Keepalived 原理 Keepalived案例 双机高可用热备案例 配置 修改配置文件 测试 严格模式测试 修改配置文件 测试 模拟故障测试 LVSKeepalived高可用 案例拓扑图 初步配置 关闭服务 主调度器配置 健康状态检查的方式 调整内核参数 从调度器配置 服务器池…

失业后才会明白,职场上有4个扎心的现象

最近一段时间&#xff0c;因为疫情的原因&#xff0c;很多企业都在经历着前所未有的困难&#xff0c;其中就包括华为这样的大型企业。 任正非在接受媒体采访的时候表示&#xff1a;“全球经济持续衰退&#xff0c;未来3到5年内都不可能转好……把寒气传递给每个人。 这句话一…

python中的魔术方法(特殊方法)

文章目录 1. 前言2. __init__方法3. __new__方法4. __call__方法5. __str__方法6. __repr__方法7. __getitem__方法8. __setitem__方法9. __delitem__方法10. __len__方法11. 富比较特殊方法12. __iter__方法和__next__方法13. __getattr__方法、__setattr__方法、__delattr__方…

深度学习DeepLearning Inference 学习笔记

神经网络预测 术语 隐藏层神经元多层感知器 神经网络概述 应当选择正确的隐藏层数和每层隐藏神经元的数量&#xff0c;以达到这一层的输出是下一层的输入&#xff0c;逐层变得清晰&#xff0c;最终输出数据的目的。 在人脸识别的应用中&#xff0c;我们将图片视作连续的像…

【Java 第九篇章】多线程实际工作中的头大的模块

多线程是一种编程概念&#xff0c;它允许多个执行路径&#xff08;线程&#xff09;在同一进程内并发运行。 一、多线程的概念和作用 1、概念 线程是程序执行的最小单元&#xff0c;一个进程可以包含多个线程。每个线程都有自己的程序计数器、栈和局部变量&#xff0c;但它们…

Motionface ai工具有哪些?

Motionface Android/PC 用一张静态含有人脸相片来生成一个能说会唱的虚拟主播。使用简单便捷&#xff0c;极致的流畅度体验超乎您的想象。 免费下载 Respeak PC电脑软件 任意视频一键生成虚拟主播&#xff0c;匹配音频嘴型同步&#xff0c;保留原视频人物神态和动作&#xff0c…

核显硬刚RTX 4070,AMD全新APU杀疯了

这年头&#xff0c;一台平民玩家低预算主流桌面电脑主机是什么配置&#xff1f; Intel i5 12400F CPU、B760 主板、NVIDIA RTX 4060 显卡、双 8G DDR4 内存、1T 固态硬盘的组合&#xff0c;想必相当具有代表性了吧&#xff01; 但仔细掰开后我们不难发现&#xff0c;这套不到…

生物信息学入门:Linux学习指南

还没有使用过生信云服务器&#xff1f;快来体验一下吧 20核心256G内存最低699元半年。 更多访问 https://ad.tebteb.cc 介绍 大家好&#xff01;作为一名生物信息学的新人&#xff0c;您可能对Linux感到陌生&#xff0c;但别担心&#xff0c;本教程将用简单明了的方式&#xff…