栈在括号匹配中的应用
目标:用栈来实现对括号序列串的匹配
![](https://i-blog.csdnimg.cn/blog_migrate/d06f7f8a2a7cb72f092fd048ba798e77.png)
tips:栈是一种操作受限的线性表,只允许在线性表的某一端进行增删操作,且遵循后进先出原则(LIFO)
简述步骤:
首先要对字符串进行逐个扫描,若扫描到的符号为左括号(‘(’||‘{’||‘【’)则压入栈顶,若为右括号(‘)’||‘}’||‘】’),则弹出栈顶元素并赋值给字符类变量,然后进行判断,若弹出的栈顶元素刚好与扫描到的右括号相互匹配,则继续向下进行扫描,若不匹配则返回FALSE。当栈空且还有未匹配的右括号时返回FALSE,当栈未空但字符串还有残余的右括号时返回FALSE,当栈空且字符串扫描完毕时返回TRUE。
需要具备的基础知识:栈的基本操作
相关基本操作的代码实现:
栈的结构体定义(此处采用的方法为创建顺序栈,也可以使用链栈来实现相关操作)
typedef struct {
char data[MaxSize];//采用数组的形式来存放栈
int top;//定义栈顶指针
} SqStack;
栈的初始化
void InitSqStack(SqStack &S) {
S.top = -1;//栈顶初始化为-1
}
压栈,出栈
bool Push(SqStack &S, char x) { //需要注意,插入元素的位置应该是在栈的下一个空位中,因此栈顶指针要先加1后在进行传值操作
if (S.top == MaxSize - 1)
return false;
S.top = S.top + 1;
S.data[S.top] = x; //博主的血泪教训:特别注意,代码的运算逻辑是先右再左,一定是x赋值给栈顶元素,左右顺序不能弄反
return true;
}
bool Pop(SqStack &S, char &x) { //先用x将栈顶元素带出,再改变指针所指向的位置{
if (S.top == -1)
return false;
x = S.data[S.top];
S.top = S.top - 1;
return true;
}
栈的判空
bool StackEmpty(SqStack S) {
if (S.top == -1)
return true;
else
return false;
}
功能模块代码逻辑:
①循环扫描数组内的每一个元素,判断是否为若为左括号则压入栈顶
②若不是左括号,判断栈是否未空,若为空,返回失败,若不为空,则弹出栈顶元素,此时可知当前扫描到的元素一定为右括号
③判断栈顶元素是否和当前扫描到的右括号相匹配,若匹配,则继续扫描下一个元素,若不匹配,则返回失败
④若扫描到右括号但栈空,则返回失败,若扫描结束但栈不为空,则返回失败
⑤若扫描结束同时判断栈为空,则代表匹配成功,返回成功
功能模块的代码实现:
bool bracketcheck(char str[], int length) {
SqStack S;
InitSqStack(S);
for (int i = 0; i < length; i++) {
if (str[i] == '(' || str[i] == '[' || str[i] == '{')
Push(S, str[i]);
else {
if (StackEmpty(S))
return false;
char topElem;
Pop(S, topElem);
if (str[i] == ')' && topElem != '(')
return false;
if (str[i] == '}' && topElem != '{')
return false;
if (str[i] == ']' && topElem != '[')
return false;
}
}
return StackEmpty(S);
}
汇总:
#define MaxSize 10
#include <stdio.h>
typedef struct {
char data[MaxSize];
int top;
} SqStack;
void InitSqStack(SqStack &S) {
S.top = -1;
}
bool StackEmpty(SqStack S) {
if (S.top == -1)
return true;
else
return false;
}
bool Push(SqStack &S, char x) { //需要注意,插入元素的位置应该是在栈的下一个空位中,因此栈顶指针要先加1后在进行传值操作
if (S.top == MaxSize - 1)
return false;
S.top = S.top + 1;
S.data[S.top] = x; //博主的血泪教训:特别注意,代码的运算逻辑是先右再左,一定是x赋值给栈顶元素,左右顺序不能弄反
return true;
}
bool Pop(SqStack &S, char &x) { //先用x将栈顶元素带出,再改变指针所指向的位置{
if (S.top == -1)
return false;
x = S.data[S.top];
S.top = S.top - 1;
return true;
}
bool bracketcheck(char str[], int length) {
SqStack S;
InitSqStack(S);
for (int i = 0; i < length; i++) {
if (str[i] == '(' || str[i] == '[' || str[i] == '{')
Push(S, str[i]);
else {
if (StackEmpty(S))
return false;
char topElem;
Pop(S, topElem);
if (str[i] == ')' && topElem != '(')
return false;
if (str[i] == '}' && topElem != '{')
return false;
if (str[i] == ']' && topElem != '[')
return false;
}
}
return StackEmpty(S);//此处判断栈是否为空,若为空,则匹配成功,若不未空,则代表检测到还有剩余的左括号,匹配失败
}
int main() {
int n;
printf("请输入想要传入字符串的长度\n");
scanf("%d\n", &n);//此处一定要加入\n,否则末尾自动占用一个字符的空间
char a[n];
for (int i = 0; i < n; i++) {
scanf("%C", &a[i]);
}
if (bracketcheck(a, n))
printf("字符串匹配");
else
printf("字符串不匹配");
return 0;
}
代码测试结果截图:
1
![](https://i-blog.csdnimg.cn/blog_migrate/7396f31bc319c686f591875eb662ea84.png)
2
![](https://i-blog.csdnimg.cn/blog_migrate/1025e6e1355cd0328b25884e9b14cef3.png)
3
![](https://i-blog.csdnimg.cn/blog_migrate/71806f904f21dc6ed3bc50908542231e.png)