如何基于栈写一个检测括号匹配程序?(新手教程)

基本原理

要编写一个这样的程序,我们首先要知道,什么是栈(stack),其实简单讲,栈就是一种后进先出(LIFO)的数据结构。

而在括号匹配中,我们可以看一个这样的例子:

假设我有“( ( ) ]”这样一组括号,其实可以很容易发现,右小括号少了一个,或者说,右中括号多了一个,可见,通过记录不同类型括号的左右两边数,好像就能实现括号匹配检测?

那么假设我有“( [ ) ]” 这样的一组括号,虽然不同类型的左右括号数相等,但整体括号却不能实现匹配。

为什么这样说?我们可以注意下自己写过的一些算式,是不是类似这样:

{1+3*[6-4*(3+1)]+1}

如果说只要个数匹配就行,那我可不可以这样写?

{1+3*(6-4*[3+1}+1])

很显然这是不行的,无论是程序代码还是数学算式,括号都不能这样匹配,但是通过观察,我们可以发现一个规律:

1.第一个式子左括号中,最后出现的“(”,与右括号中,最先出现的“)”匹配,中括号同理。

2.第二个式子左括号中,最后出现的“【”,与右括号中,最先出现的“}”,并不匹配。

我们不难得出一个结论:最后出现的左括号,往往越着急与最先出现的右括号匹配。

编写代码

要想判断所有的括号是否匹配,我们要先判断任意两个括号是否匹配。

int MatchChar(char a, char b)
{
	if ((a == '(' && b == ')') || (a == '[' && b == ']') || (a == '{' && b == '}'))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

在这个函数中,我们任意输入两个括号,然后返回这两个括号的匹配结果,其中a为任意类型的左括号,b为同类型的右括号。

我们知道,我们需要让右括号去匹配左括号,所以要想办法把左括号存起来,即:压入栈,等待右括号与之匹配,这样,我们就能保证最后进入的左括号,始终最先去匹配

可能匹配失败情况有以下几种:

1.左右括号不匹配(MatchChar返回0)

2.缺少左括号(右侧括号匹配时,栈空)

3.左括号剩余(右括号匹配完成,还有左括号剩余)

编写代码如下:

stack<char>s;
int MatchExp(char exp[])
{
	for (int i = 0; exp[i] != '\0'; i++)
	{
		if (exp[i] == '(' || exp[i] == '[' || exp[i] == '{')
		{
			s.push(exp[i]); //如果是左括号,就入栈
		}
		else //如果是右括号
		{
			if (s.empty())return 0; //栈空,没有左匹配右,失败
			else
			{
				if (!MatchChar(s.top(), exp[i]))return 0; //左右括号不匹配
				else s.pop(); //匹配成功,栈顶元素出栈
			}
		}
	}
	if (!s.empty())return 0; //匹配完时还要左括号剩余,失败
	return 1;
}

最后,我们来看全部代码:

#include<iostream>
#include<stack>
using namespace std;
stack<char>s;
int MatchChar(char a, char b)
{
	if ((a == '(' && b == ')') || (a == '[' && b == ']') || (a == '{' && b == '}'))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int MatchExp(char exp[])
{
	for (int i = 0; exp[i] != '\0'; i++)
	{
		if (exp[i] == '(' || exp[i] == '[' || exp[i] == '{')
		{
			s.push(exp[i]);
		}
		else
		{
			if (s.empty())return 0;
			else
			{
				if (!MatchChar(s.top(), exp[i]))return 0;
				else s.pop();
			}
		}
	}
	if (!s.empty())return 0;
	return 1;
}

void Result(int result)
{
	if (result)cout << "匹配成功!";
	else cout << "匹配失败!";
}

int main()
{
	char exp[100] = {};
	scanf("%s", exp);
	Result(MatchExp(exp));
	return 0;
}

测试运行

感谢阅读!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值