zoukankan      html  css  js  c++  java
  • 栈应用之括号匹配问题

    问题描述

    括号匹配问题,即给定一段文本text,括号是否有正确匹配的问题。括号由一个开括号如"(“和一个闭括号”)“组成,相互对应。这里只考虑三种括号,即”()","[]","{}"。此外括号括起的片段,也可能会嵌套。

    解决思路

    这样就不难总结出检查括号配对的原则:从左到右遍历text时,遇到的闭括号应该与最近遇到的且尚未匹配的开括号配对。
    由于括号的出现可能嵌套,需要逐对匹配,即当前闭括号应该与前面最近的尚未配对的开括号匹配,下一个闭括号则与前面次近的括号匹配。也就是说,需要存储的开括号的使用原则是后存入着先使用,即LIFO。进而如果一个开括号已经配对,就应删除这个括号,为后面匹配作准备,显然使用栈保存遇到的开括号,配对后再相应地pop掉最近的开括号就可以正确支持这样的匹配任务。
    比如对于text="(dsaf[sd]d}",我们顺序遍历,将两个开括号"(“和”[“顺序压入栈中,然后遇到第一个闭括号”]“与此时的栈顶”[“匹配,匹配成功就将该栈顶弹出并继续,此时栈顶变成了第一个压入栈中的”(",然后继续遍历,遇到闭括号"}“与此时的栈顶”(“不匹配,说明整个text括号匹配不成功。
    当然还熬考虑这种情况text=”(dsaf[sd]d",按照上面的思路是不能检测到"("丢失匹配的情况的,我们可以在遍历text结束时再查看栈中是否还有剩余的元素,如果有,说明是丢失匹配的开括号。
    于是算法思路如下:

    • 顺序遍历给定text的一个个字符
    • 对于除了括号之外的无关字符直接跳过
    • 遇到开括号就压入栈
    • 遇到比闭括号就弹出当时的栈顶元素与之匹配
    • 如果匹配成功则继续,如果不匹配则以失败结束
    • 遍历text完毕时,检查栈中是否为空,如果为空说明括号完全匹配,否则打印出丢失匹配的开括号。

    代码如下:

    # -*- coding: utf-8 -*-
    # @Author: Jiang Ji
    # @Date:   2020-04-08 22:24:07
    # @Last Modified by:   Jiang Ji
    # @Last Modified time: 2020-04-09 09:41:40
    
    
    class StackUnderflow(ValueError):
        '''自定义栈相关的异常类
        '''
        pass
    
    
    class SStack:
        '''基于顺序表实现的栈类
        '''
    
        def __init__(self):
            self._elems = []  # 用list对象 _elems存储栈中元素
    
        def is_empty(self):
            return self._elems == []
    
        def top(self):  # 取得最后压入的元素,即栈顶
            if self._elems == []:
                raise StackUnderflow("in SStack.pop()")
            else:
                return self._elems[-1]
    
        def push(self, elem):  # 压栈
            self._elems.append(elem)
    
        def pop(self):  # 出栈
            if self._elems == []:
                raise StackUnderflow("in SStack.pop()")
            return self._elems.pop()
    
    
    def check_parens(text):
        parens = "()[]{}"  # 所有括号字符
        open_parens = "([{"  # 开括号字符
        opposite = {")": "(", "]": "[", "}": "{"}
    
        def parentheses(text):
            '''括号生成器,每次调用返回text里的下一个括号及其位置
            '''
            i, text_len = 0, len(text)
            while True:
                while i < text_len and text[i] not in parens:
                    i += 1
                if i >= text_len:
                    return
                yield text[i], i
                i += 1
        st = SStack()  # 保存括号的栈
        dict = {}  # 存储括号及对应标号的字典
        for pr, i in parentheses(text):  # 对各括号和位置迭代
            dict[pr] = i
            if pr in open_parens:
                st.push(pr)  # 如果是开括号,压栈并继续
            elif st.pop() != opposite[pr]:  # 否则就是匹配失败
                print("Unmatching id found at", i, "for", pr)
                return False
        #  检查是否有丢失匹配的开括号
        if not st.is_empty():
            while not st.is_empty():
                print("Missed id found at", dict[st.top()], "for", st.top())
                st.pop()
            return False
        else:
            print("All parentheses are correctly matched.")
            return True
    
    
    if __name__ == "__main__":
        text = "(da)(d}s{a"
        check_parens(text)
    

    作者INFO
    作者:JohnJim,某985本硕生,研究领域为机器人,对机器学习、强化学习以及机器视觉等方面感兴趣。
    公众号:个人公众号【J平方】,合作公众号【AI算法驿站】

  • 相关阅读:
    跨站脚本攻击—XSS
    ElasticSearch ClusterBlockException[blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];
    mysql报Can't create/write to file '/tmp/ib0n3frL' (Errcode: 13
    Vue项目关闭ESLint + Prettier代码规范
    SpringBoot读取Resource下文件的几种方式
    elasticsearch5.6.1.集成springboot 遇到的坑
    如何利用XShell隧道通过跳板机连接内网机器
    重置windows10 WSL中ubuntu的密码
    【php】phpstorem201922破解版安装,亲测可以
    【死磕NIO】— 阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO,这你真的分的清楚吗?
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13281666.html
Copyright © 2011-2022 走看看