数据结构:用栈实现括号匹配(Python 可运行示例)
数据结构用栈实现括号匹配Python 可运行示例本章要点栈是一种“后进先出”的数据结构在括号匹配问题中展现出了优雅的工程价值。除了教科书上的基础应用括号匹配算法在真实项目中随处可见代码编辑器VS Code、PyCharm的语法高亮、编译器的语法分析、JSON/XML/HTML配置文件的格式校验甚至Markdown渲染中的标签闭合检查都依赖这一核心逻辑。掌握它你就掌握了自动化语法检查的入门钥匙。原理简述括号匹配的核心思想是“最近出现的左括号必须与最先出现的右括号匹配”。栈恰好能满足这一需求- 遇到左括号(,[,{压入栈- 遇到右括号),],}检查栈顶是否为对应的左括号- 最终栈为空则匹配成功关键点栈顶元素代表“最新的未匹配左括号”这天然符合嵌套结构的特性。示例代码以下是完整的可运行Python代码包含详细注释和多种测试用例class BracketMatcher: 括号匹配器支持 (), [], {} 三种括号 def __init__(self): # 括号映射表右括号 - 对应左括号 self.matching_pairs { ): (, ]: [, }: { } # 左括号集合用于快速判断 self.open_brackets set(self.matching_pairs.values()) def is_balanced(self, s: str) - bool: 检查字符串中的括号是否匹配 :param s: 待检查的字符串可包含其他字符 :return: True 表示匹配False 表示不匹配 # 使用列表模拟栈 stack [] for i, char in enumerate(s): # 如果是左括号压入栈 if char in self.open_brackets: stack.append(char) print(f 位置 {i}: 压入 {char}当前栈: {stack}) # 如果是右括号检查匹配 elif char in self.matching_pairs: expected self.matching_pairs[char] # 栈为空说明没有对应的左括号 if not stack: print(f 位置 {i}: 错误遇到 {char} 但栈为空) return False # 栈顶元素不匹配 top stack.pop() if top ! expected: print(f 位置 {i}: 错误期望 {expected}但栈顶是 {top}) return False else: print(f 位置 {i}: 匹配 {top} 和 {char}当前栈: {stack}) # 非括号字符忽略 else: print(f 位置 {i}: 忽略字符 {char}) # 最终检查栈是否为空 if stack: print(f 错误还有未匹配的左括号: {stack}) return False print( ✓ 括号完全匹配) return True # 测试用例 def run_tests(): matcher BracketMatcher() test_cases [ # (测试编号, 描述, 输入, 预期结果) (1, 空字符串, , True), (2, 简单匹配, (), True), (3, 嵌套括号, ({[]}), True), (4, 混合括号, a*(bc)-[d/e], True), (5, 缺少右括号, ({[, False), (6, 缺少左括号, )]}, False), (7, 顺序错误, (], False), (8, 复杂表达式, def func(x): return (x 1) * [1, 2, 3], True), (9, 不匹配的嵌套, ([)], False), # 经典错误案例 ] for id, desc, input_str, expected in test_cases: print(f\n测试 {id}: {desc}) print(f输入: {input_str}) print(f预期: {匹配 if expected else 不匹配}) result matcher.is_balanced(input_str) status ✓ if result expected else ✗ print(f实际: {匹配 if result else 不匹配} {status}) if result ! expected: print(f ⚠ 测试失败预期 {expected}得到 {result}) print(- * 50) if __name__ __main__: run_tests()代码调试技巧1.启用详细日志代码中加入了打印语句可以看到每一步的栈状态便于调试2.测试用例覆盖包括空字符串、简单匹配、嵌套、缺失括号、顺序错误等典型场景3.经典错误案例([)]这种看似对称但实际不匹配的情况能帮你理解栈的“后进先出”特性常见错误分析| 错误类型 | 现象 | 原因 ||---------|------|------|| 栈为空时遇到右括号 | 程序报错或返回False | 缺少对应左括号 || 遍历结束栈非空 | 返回False | 左括号没有闭合 || 括号顺序错误 | 如([)]返回False | 栈顶元素与当前右括号不匹配 || 忽略非括号字符 | 正常处理 | 需要明确过滤规则 |复杂度-时间复杂度O(n)只需一次遍历-空间复杂度O(n)最坏情况下栈中存储所有左括号常见坑1.忘记处理空栈遇到右括号时必须先检查栈是否为空2.忽略字符过滤实际应用中字符串可能包含字母、数字、运算符等需要只处理括号字符3.混淆括号类型不同的括号圆括号、方括号、花括号不能混用匹配4.栈的模拟方式Python中建议用list而非自定义类避免性能开销5.编码问题注意全角/半角括号的区别中文括号【】需要额外处理真实项目应用场景括号匹配算法在以下场景中直接落地-代码编辑器实时高亮不匹配的括号帮助程序员快速定位错误-编译器/解释器语法分析的第一步检查括号是否配对-配置文件解析JSON、XML、YAML等格式的括号/标签闭合验证-数学表达式计算确保表达式的括号结构正确掌握了括号匹配你就掌握了栈在“最近相关性”问题中的核心应用。在算法面试中这个问题常常作为“栈的入门题”后续还会扩展到表达式求值、函数调用栈、浏览器的前进后退等更复杂的应用场景。*如果你对栈的其他应用如逆波兰表达式计算、迷宫求解感兴趣可以继续关注后续章节。掌握这些基础面试中遇到栈相关的问题就能游刃有余。*