zoukankan      html  css  js  c++  java
  • 验证()、{}、[]三种括号是否成对出现的方法(利用压栈弹栈实现)

    原文链接:https://blog.csdn.net/mrdeng_web2018/article/details/108426604

    近期遇到个问题,需要验证用户输入的字符串中(),小括号是否匹配,是否成对,顺序对不对。

    我的需求虽然是只需要考虑到(),是否匹配,但作者把[]、{}也顺带实现了,若果只需要检测某一种括号,将map里的键值对去掉多余的即可,很棒!

    我用的是vue项目,所以直接写成工具

     bracketMatch.js

    //   定义栈的类
    class bracketMatchStack {
        constructor() {
            this.stack = [];
        }
        push(item) {
            return this.stack.push(item);
        }
        pop() {
            return this.stack.pop();
        }
        // 查询栈顶的元素
        peek() {
            return this.stack[this.getSize() - 1];
        }
        //返回栈的长度
        getSize() {
            return this.stack.length;
        }
        // 栈的非空判断
        isEmpty() {
            return this.getSize() === 0;
        }
    }
    export function  testBracketIsValid(str) {
        // 以左右括号来建立一个对象,key为左括号,value为右括号
        var Map = {
            "{": "}",
            "(": ")",
            "[": "]",
        };
        //实例化一个栈
        const myStack = new bracketMatchStack();
        //遍历str字符串
        for (let v of str) {
            if (Map[v]) {
                myStack.push(v); //是左括号,入栈
            } else if (Object.values(Map).includes(v)) {
                // 右括号  将当前的元素和栈顶的第一个元素进行匹配
                let last = myStack.pop();
                if (v !== Map[last]) return false;
            } else {
            //这里排除的是空字符的情况,如果不是左右括号而是其他的空字符串或者非法字符的话,将终止本次循环,执行下一次循环
                continue;
            }
        }
        //遍历完成之后要保证栈内要为空
        return myStack.getSize() === 0;
    }

    在项目中使用:

    引入

    import {testBracketIsValid} from "@/utils/bracketMatch"

    使用:

          str1 :"(dfsdfsdfsd)dasdadas()(())",
          str2:"(dgdfdgfd(fgdgfd)",
          str3 :"(dfsdfsdfsd)dasdadas()(({}))",
          str4:"[dgdfdgfdfgdgfd]",
          str5:")(",
          str6:"()(",
        console.log(testBracketIsValid(this.str1));//true
        console.log(testBracketIsValid(this.str2));//false
        console.log(testBracketIsValid(this.str3));//true
        console.log(testBracketIsValid(this.str4));//true
        console.log(testBracketIsValid(this.str5));//false
        console.log(testBracketIsValid(this.str6));//false

    总结:

    很多人说用了栈的先进后出特点,但是我觉得对于一个纯前端来说,一直就用js,说栈显的有点深奥,对新手不友好,(先进后出,我觉得是很正常的,还原理什么,有点深奥,相信一直使用js的人,不需要去解释这一点,这一切都很自然,不需要用栈来解释)。

    压栈其实就是数组的push方法(想数组最后添加元素),弹出栈,就是pop方法(去除数组内的最后一位元素)。

    用for of遍历字符串,遇见左括号就将左括号push进去(说栈也可以说数组也行)。遇到右括号,就将数组最后的左括号pop出去(弹出);如果当前的右括号与弹出的括号不是一个类型则返回false,这可以确定,括号的匹配有问题了,就返回false。如果遇到不是括号的元素直接结束本次循环,继续下一次循环(continue)。最后,看看数组内是否清除干净,如果不干净,数组长度部位0,代表括号不是成对出现的,是奇数,返回false。这样就可以检验括号是否成对出现以及匹配是否正确,感谢作者的文章,让我拓宽点小技能。

     ===============================

    改成自己所需要的的插件:

    需求:

    1、我只需要检查()小括号是否成对出现,出现位置是否合法即可,不需要验证{}、[]。

    2、我需要知道最外层小括号的内容

     思路:以上不合法是返回true、false,我想让合法时,返回最外层小括号内的内容,最外层小括号可能有无限个,当合法时我返回一个数组,里存放着所有最外层小括号的内容,不合法时依然返回false。

    怎么判断是最外层小括号呢?

    当压栈后,数组长度为1时,此时的小括号就是最外层左小括号。记录索引

    弹栈前,数组长度为1时,此时是最外层右小括号。记录索引。然后截取中间的内容,就是最外层小括号的内容,之后将这些信息存到一个对象里,push到盛放最外层小括号内容的数组内。

    验证成功后将这个数组返回出去。

    具体代码实现:

     bracketMatch.js

    //   定义栈的类
    class bracketMatchStack {
        constructor() {
            this.stack = [];
        }
        push(item) {
            return this.stack.push(item);
        }
        pop() {
            return this.stack.pop();
        }
        // 查询栈顶的元素
        peek() {
            return this.stack[this.getSize() - 1];
        }
        //返回栈的长度
        getSize() {
            return this.stack.length;
        }
        // 栈的非空判断
        isEmpty() {
            return this.getSize() === 0;
        }
    }
    export function  testBracketIsValid(str) {
        // 以左右括号来建立一个对象,key为左括号,value为右括号
        var Map = {
            "(": ")",
        };
        var outerMostBracketValue = [];//最外层括号的内容
        //实例化一个栈
        const myStack = new bracketMatchStack();
        //遍历str字符串
        var start = 0;//用来记录最外层左括号的索引 只有最外层左括号时这个值才会变
        for (let index = 0; index < str.length;index++) {
            let v = str[index];
            if (Map[v]) {
                myStack.push(v); //是左括号,入栈
                if(myStack.getSize() == 1){//第一个左括号就是最外层
                    start = index;//最外层左括号的索引
                }
            } else if (Object.values(Map).includes(v)) {
                // 右括号  将当前的元素和栈顶的第一个元素进行匹配
                if(myStack.getSize() == 1){//最外层右括号时
                    let o = {
                        start:start,//最外层左括号索引
                        end:index,//最外层右括号索引
                        value:str.substring(start,index + 1),//最外层括号的值
                    }
                    outerMostBracketValue.push(o);
                }
                let last = myStack.pop();
                if (v !== Map[last]) return false;
            } else {
            //这里排除的是空字符的情况,如果不是左右括号而是其他的空字符串或者非法字符的话,将终止本次循环,执行下一次循环
                continue;
            }
        }
        //遍历完成之后要保证栈内要为空
        if(myStack.getSize() === 0){
            return outerMostBracketValue;
        }else {
            return false;
        }
    }

    使用:

    data(){
        return{
          str1 :"(dfsdfsdfsd)dasdadas()(())",
          str2:"(dgdfdgfd(fgdgfd)",
          str3 :"(dfsdfsdfsd)dasdadas()(({}))",
          str4:"[dgdfdgfdfgdgfd]",
          str5:")(",
          str6:"()(",
        }
      },
      mounted(){
        console.log(testBracketIsValid(this.str1));
        console.log(testBracketIsValid(this.str2));
        console.log(testBracketIsValid(this.str3));
        console.log(testBracketIsValid(this.str4));
        console.log(testBracketIsValid(this.str5));
        console.log(testBracketIsValid(this.str6));
      }

    结果:

  • 相关阅读:
    9.1 正则介绍_grep上 9.2 grep中 9.3 grep下
    汉诺塔递归问题
    8.10 shell特殊符号cut命令 8.11 sort_wc_uniq命令 8.12 tee_tr_split命令 8.13 shell特殊符号下
    8.6 管道符和作业控制 8.7/8.8 shell变量 8.9 环境变量配置文件
    8.1 shell介绍 8.2 命令历史 8.3 命令补全和别名 8.4 通配符 8.5 输入输出重定向
    socket中使用序列化传结构体
    C# get,set属性用法
    Log4Net如何将日志按不同类型写入多个文件中
    app.config文件的configation标签中加代码引起”配置系统未能初始化“
    WinForm下使用 log4net
  • 原文地址:https://www.cnblogs.com/fqh123/p/14057739.html
Copyright © 2011-2022 走看看