我们先来看一道题:
任意给定一个字符串,字符串中包含除了空白符,换行符之外的任意字符。你的任务是检测字符串中的圆括号是否配对,比如说"((a+b)*(c+d))"中的圆括符就是配对的,而"((a+b)))*(c+d)"就不配对。
初看此题很多人会理所当然地认为只要括号数量相同就能配对,然而真的是这样吗?我们看一下例子((a+b)+((c+d)*(1+c))),这个字符串的括号明显是配对的,我们随意调换括号之间的顺序,显然括号总数没有变,然而这个——))a+b(+))c+d(*(1+c(((显然就离谱了。
接下来开始分析这个题目:
不配对的一共有一下几种情况:
1,括号数量不匹配。
2,存在一个括号找不到相对应的括号。
这里相对应的意思是指逻辑上的对应,不是简单的数量上的对应,如果能达到2满足的一一对应的要求那么他们数量上的要求也就满足了。接下来为了简化问题,我们把一个字符串中的所有圆括号都拿出来单独作为一个数组来研究。为了简单起见,我定义了一个整形数组,并且用1表示'(',2表示')'。举个例子,对于字符串"(((a+b)+(c+d)*(d+f))+(5-f))"经过转化后就以{1,1,1,2,1,2,1,2,2,1,2,2}的形式储存在了一个整形数组中。我们发现相邻的1,2代表他们是原来字符串中最内层的括号,可以直接“消掉”,间隔为两个括号的1,2代表他们是原来字符串中倒数第二层的括号,接着“消掉”……重复这个过程,倘若我们把“消掉”定义成0。那我们就以{1,1,1,2,1,2,1,2,2,1,2,2}为例,第一层消掉间隔为0的1,2后变为{110000002002},第二层消掉间隔为2的后不变依然为{110000002002},第三层依然不变,第四次消去间隔为6处理后变为{100000000002}……最后将在第六次消去后变为{0,0,0,0,0,0,0,0,0,0,0,0}。当全部为0时表示一对一对消去成功,自然就说是括号配对了。
下面是仓促写就的代码,新手村之间可以互相交流,也欢迎大神前来改进:
#include<stdio.h>
int main()
{
char a[100];
gets(a);//输入字符串数组
int i = 0, b[100] = { 0 },j=0;
while (a[i] != '\0')//把括号类型转变为int类型,如((a+b)*((c+d)+5))将会被转化为11211222储存在b中
{
if (a[i] == '(')
{
b[j++] = 1;
}
else if(a[i]==')')
{
b[j++] = 2;
}
i++;
}
for (int m = 1; m <=50; m += 2)//对括号由小到大消去,从相邻的括号开始消,如第一次消去后b[]变为10010022
{
for (int k = 0; k < j-m; k++)
{
if (b[k] == 1 && b[k + m] == 2)
{
b[k] = 0;
b[k + m] = 0;
}
}
int sum = 0;
for (int n = 0; n < j; n++)
{
sum += b[n];
}
if (sum == 0)
{
printf("yes配对");
return 0;
}
}
printf("no未配对");
}
各位读者也可自行思考如何将这个思路应用于多种括号的配对判断,也可以思考如何加入对括号逻辑的更进一步判断,比如说"(((a+b)))"中外围两层括号是毫无必要的(可能下一期就写这个)。这里用的都是基础语句,主要提供初学者交流学习之用。