验证()、{}、[]三种括号是否成对出现的方法(利用压栈弹栈实现)

原文链接: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));
  }

结果:

 

 

 

 

 

 

 

 

posted @ 2020-11-29 20:23  古墩古墩  Views(668)  Comments(0Edit  收藏  举报