CB2-判断表达式中圆括号是否配对
代码实现
| C |
|---|
| #include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 1000 // 栈的最大容量
/**
* 栈的顺序存储结构定义
*/
typedef struct {
char data[MAXSIZE]; // 存储栈元素的数组
int top; // 栈顶指针
} Stack;
/**
* 判断表达式中圆括号是否配对
* @param A 字符串表达式
* @return 括号配对返回true,不配对返回false
*/
bool fun(char A[]) {
// 初始化栈
Stack s;
s.top = -1;
// 遍历表达式中的每个字符
for (int i = 0; A[i] != '\0'; i++) {
// 如果是左圆括号,入栈
if (A[i] == '(') {
// 检查栈是否已满
if (s.top == MAXSIZE - 1) {
printf("栈溢出\n");
return false;
}
s.data[++s.top] = '(';
}
// 如果是右圆括号,检查配对
else if (A[i] == ')') {
// 检查栈是否为空(没有对应的左括号)
if (s.top == -1) {
return false; // 右括号多余
}
s.top--; // 匹配成功,出栈
}
// 其他字符忽略
}
// 最后检查栈是否为空
if (s.top == -1) {
return true; // 所有括号都配对
} else {
return false; // 左括号多余
}
}
|
算法执行流程图解
正确配对示例:
| Text Only |
|---|
| 表达式:"(a+b)*(c-d)"
执行过程:
i=0: '(' → 入栈:栈['('], top=0
i=1: 'a' → 忽略
i=2: '+' → 忽略
i=3: 'b' → 忽略
i=4: ')' → 出栈:栈[], top=-1
i=5: '*' → 忽略
i=6: '(' → 入栈:栈['('], top=0
i=7: 'c' → 忽略
i=8: '-' → 忽略
i=9: 'd' → 忽略
i=10:')' → 出栈:栈[], top=-1
结束:top=-1,返回true
|
错误配对示例1(右括号多余):
| Text Only |
|---|
| 表达式:"(a+b))"
执行过程:
i=0: '(' → 入栈:栈['('], top=0
i=1: 'a' → 忽略
i=2: '+' → 忽略
i=3: 'b' → 忽略
i=4: ')' → 出栈:栈[], top=-1
i=5: ')' → 栈空,返回false
|
错误配对示例2(左括号多余):
| Text Only |
|---|
| 表达式:"(a+b"
执行过程:
i=0: '(' → 入栈:栈['('], top=0
i=1: 'a' → 忽略
i=2: '+' → 忽略
i=3: 'b' → 忽略
结束:top=0≠-1,返回false
|
算法状态变化图解
| Text Only |
|---|
| 表达式:"( ( a + b ) * ( c - d ) )"
栈状态变化:
初始: [] top=-1
'(': ['('] top=0
'(': ['(']['('] top=1
')': ['('] top=0
'(': ['(']['('] top=1
')': ['('] top=0
')': [] top=-1
最终top=-1,括号配对正确
|
复杂度分析
时间复杂度:O(n)
- 遍历时间:需要遍历整个字符串一次,O(n)
- 栈操作:每次入栈/出栈操作O(1)
- 总体时间复杂度:O(n)
空间复杂度:O(n)
- 栈空间:最坏情况下所有左括号都入栈,O(n)
- 辅助变量:常数个变量,O(1)
- 总体空间复杂度:O(n)
多种括号类型拓展版本
| C |
|---|
| /**
* 判断表达式中多种类型括号是否配对
* 支持:圆括号()、方括号[]、花括号{}
* @param A 字符串表达式
* @return 括号配对返回true,不配对返回false
*/
bool fun_multiple(char A[]) {
Stack s;
s.top = -1;
for (int i = 0; A[i] != '\0'; i++) {
char ch = A[i];
// 如果是左括号,入栈
if (ch == '(' || ch == '[' || ch == '{') {
if (s.top == MAXSIZE - 1) {
printf("栈溢出\n");
return false;
}
s.data[++s.top] = ch;
}
// 如果是右括号,检查配对
else if (ch == ')' || ch == ']' || ch == '}') {
// 检查栈是否为空
if (s.top == -1) {
return false;
}
// 检查括号类型是否匹配
char top_ch = s.data[s.top];
if ((ch == ')' && top_ch == '(') ||
(ch == ']' && top_ch == '[') ||
(ch == '}' && top_ch == '{')) {
s.top--; // 匹配成功,出栈
} else {
return false; // 类型不匹配
}
}
// 其他字符忽略
}
// 检查是否所有括号都已配对
return (s.top == -1);
}
|
优化版本(使用辅助函数)
| C |
|---|
| /**
* 判断是否为左括号
*/
bool isLeftBracket(char ch) {
return (ch == '(' || ch == '[' || ch == '{');
}
/**
* 判断是否为右括号
*/
bool isRightBracket(char ch) {
return (ch == ')' || ch == ']' || ch == '}');
}
/**
* 判断括号是否匹配
*/
bool isMatchingPair(char left, char right) {
return (left == '(' && right == ')') ||
(left == '[' && right == ']') ||
(left == '{' && right == '}');
}
/**
* 优化版本的多类型括号匹配
*/
bool fun_optimized(char A[]) {
Stack s;
s.top = -1;
for (int i = 0; A[i] != '\0'; i++) {
char ch = A[i];
if (isLeftBracket(ch)) {
if (s.top == MAXSIZE - 1) return false;
s.data[++s.top] = ch;
}
else if (isRightBracket(ch)) {
if (s.top == -1) return false;
if (isMatchingPair(s.data[s.top], ch)) {
s.top--;
} else {
return false;
}
}
}
return (s.top == -1);
}
|
更完整的括号匹配检查
| C |
|---|
| /**
* 完整版本:提供详细的错误信息
*/
typedef enum {
VALID,
EXTRA_LEFT,
EXTRA_RIGHT,
MISMATCH
} BracketStatus;
BracketStatus check_brackets_detailed(char A[]) {
Stack s;
s.top = -1;
for (int i = 0; A[i] != '\0'; i++) {
char ch = A[i];
if (isLeftBracket(ch)) {
if (s.top == MAXSIZE - 1) return EXTRA_LEFT;
s.data[++s.top] = ch;
}
else if (isRightBracket(ch)) {
if (s.top == -1) return EXTRA_RIGHT;
if (isMatchingPair(s.data[s.top], ch)) {
s.top--;
} else {
return MISMATCH;
}
}
}
return (s.top == -1) ? VALID : EXTRA_LEFT;
}
|
测试用例
| C |
|---|
| /**
* 测试函数
*/
void test_bracket_matching() {
char* test_cases[] = {
"()", // true
"()[]{}", // true
"([{}])", // true
"([)]", // false - 交叉匹配
"(((", // false - 左括号多余
")))", // false - 右括号多余
"", // true - 空字符串
"a+b*(c-d)", // true - 混合字符
"({[}])" // false - 类型不匹配
};
int num_tests = sizeof(test_cases) / sizeof(test_cases[0]);
for (int i = 0; i < num_tests; i++) {
bool result = fun_multiple(test_cases[i]);
printf("表达式: %s -> %s\n",
test_cases[i],
result ? "配对正确" : "配对错误");
}
}
|
算法特点
核心思想:
利用栈的后进先出特性,左括号入栈,右括号时检查栈顶是否为对应的左括号。
关键技巧:
1. 类型匹配:确保括号类型正确对应
2. 数量匹配:确保左右括号数量相等
3. 顺序匹配:确保括号嵌套顺序正确
应用场景:
- 编译器语法检查
- 代码编辑器括号高亮
- 数学表达式验证
- XML/HTML标签匹配
易错点:
1. 忘记检查栈空情况
2. 括号类型匹配错误
3. 忽略其他字符的处理
4. 最终栈状态检查遗漏
这种括号匹配算法是栈应用的经典案例,在实际开发中非常实用。