JavaScript数据结构之栈实例用法


Posted in Javascript onJanuary 18, 2019


先来看一道题

Leetcode 32 Longest Valid Parentheses (最长有效括号)

给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"

示例 2:

输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"

这道题可以用动态规划来做,也能用简洁明了的栈来解决。

什么是栈?

栈是一种先进后出(LIFO)的有序集合,新添加的元素在栈顶,旧元素在栈底。

以下图为例,1、2、3、4、5、6、7先后进栈:

JavaScript数据结构之栈实例用法

创建栈

创建一个类来表示栈:

class Stack {
 // 初始化类,创建数组 items 存放入栈元素
 constructor() {
  this.items = [];
 }
 // push 方法进行元素入栈(可同时入栈一或多个元素),无返回值
 push() {
  this.items.push(...arguments);
 }
 // pop 方法出栈一个元素,返回出栈元素
 pop() {
  return this.items.pop();
 }
 // peek 方法返回栈顶元素,不对栈本身做任何操作
 peek() {
  return this.items[this.items.length-1];
 }
 // size 方法返回栈内元素个数
 size() {
  return this.items.length;
 }
 // isEmpty 方法查看栈是否为空,返回布尔值
 isEmpty() {
  return this.items.length == 0;
 }
 // clear 方法清空栈,无返回值
 clear() {
  this.items = [];
 }
 // print 方法打印栈内元素
 print() {
  console.log(this.items.toString());
 }
}
 
// 测试 
let stack = new Stack();
stack.push(1,2,3,4);
stack.print(); // 1,2,3,4
stack.isEmpty(); // false
stack.size(); // 4
stack.pop(); // 4
stack.peek(); // 3
stack.clear();

注意

因为 JavaScript 的类内暂时无法定义私有成员,所以可以在类外访问到存储栈元素的数组 items,这个操作是很危险的。

stack.items; // [1, 2, 3, 4]

这时可以使用闭包和IIFE进行避免,这是一个很无奈的办法:

let Stack = (function () {
 // 使用 WeakMap 存储数组(数组存放进栈元素)
 let items = new WeakMap();
 class Stack {
  constructor() {
   items.set(this, []);
  }
  push() {
   items.get(this).push(...arguments);
  }
  // 其他方法
 }
 return Stack;
})();
 
let s = new Stack();
// 无法访问到 items
s.items; // undefined

WeakMap: WeakMap是类似Map的键值对集合,但WeakMap的键是弱引用的,只要不存在引用,垃圾回收机制就会回收掉占用的内存,相当于自动删除,而不用手动删除。

用栈解题

思路:

变量start存放有效括号起始下标,maxLen存放最大长度;

栈只存放左括号的下标,遇到左括号,将其下标存入栈中;

遇到右括号,若此时栈为空,跳过本次循环并更新start;若栈不为空,则栈顶元素出栈;

栈顶元素出栈后,若栈为空,则计算当前下标和start的距离,并更新maxLen;

栈顶元素出栈后,若栈不为空,则计算当前下标和栈顶存放的下标的距离,并更新maxLen;

循环遍历直至结束。

function test(str) {
 let stack = new Stack();
 let start = 0;
 let maxLen = 0;
 
 for(let i=0; i<str.length; i++) {
  // 如果是左括号,下标入栈
  if (str[i] == '(') {
   stack.push(i);
  } else {
   // 如果是右括号
   /* 栈内为空,说明本次有效括号匹配已结束,跳过本次循环并更新 start */
   if (stack.isEmpty()) {
    start = i+1;
    continue;
   } else {
    // 栈内不为空,则出栈一个左括号进行匹配
    stack.pop();
    // 栈顶元素出栈后,栈为空
    if (stack.isEmpty()) {
     // 根据当前下标和 start 去更新 maxLen
     maxLen = Math.max(maxLen, i-start+1);
    } else {
     // 栈不为空,根据当前下标和栈顶存放的下标去更新 maxLen
     maxLen = Math.max(maxLen, i-stack.peek());
    }
     
   }
  }  
 }
  
 return maxLen;
}
 
test('(()'); // 2
test(')()())'); // 4
Javascript 相关文章推荐
Prototype使用指南之range.js
Jan 10 Javascript
jquery 多行滚动代码(附详细解释)
Jun 17 Javascript
JQuery教学之性能优化
May 14 Javascript
原生js封装二级城市下拉列表的实现代码
Jun 16 Javascript
Bootstrap编写一个在当前网页弹出可关闭的对话框 非弹窗
Jun 30 Javascript
JS监听微信、支付宝等移动app及浏览器的返回、后退、上一页按钮的事件方法
Aug 05 Javascript
浅谈 vue 中的 watcher
Dec 04 Javascript
Vue 实现树形视图数据功能
May 07 Javascript
深入浅析js原型链和vue构造函数
Oct 25 Javascript
vue element 中的table动态渲染实现(动态表头)
Nov 21 Javascript
微信小程序scroll-view实现滚动到锚点左侧导航栏点餐功能(点击种类,滚动到锚点)
Jun 11 Javascript
js实现鼠标点击飘爱心效果
Aug 19 Javascript
Vue核心概念Action的总结
Jan 18 #Javascript
js取小数点后两位四种方法
Jan 18 #Javascript
jQuery移动端跑马灯抽奖特效升级版(抽奖概率固定)实现方法
Jan 18 #jQuery
jquery获取file表单选择文件的路径、名字、大小、类型
Jan 18 #jQuery
jQuery实现适用于移动端的跑马灯抽奖特效示例
Jan 18 #jQuery
js数组去重的方法总结
Jan 18 #Javascript
jQuery实现的3D版图片轮播示例【滑动轮播】
Jan 18 #jQuery
You might like
简单的PHP图片上传程序
2008/03/27 PHP
PHP获取一段文本显示点阵宽度和高度的方法
2015/03/12 PHP
SAE实时日志接口SDK用法示例
2016/10/09 PHP
PHP Post获取不到非表单数据的问题解决办法
2018/02/27 PHP
10个基于jQuery或JavaScript的WYSIWYG 编辑器整理
2010/05/06 Javascript
jQuery实现可用于博客的动态滑动菜单完整实例
2015/09/17 Javascript
JavaScript实现简洁的俄罗斯方块完整实例
2016/03/01 Javascript
jQuery移动端图片上传组件
2016/06/12 Javascript
jQuery实现可兼容IE6的滚动监听功能
2017/09/20 jQuery
基于vue实现分页效果
2017/11/06 Javascript
Angular实现下拉框模糊查询功能示例
2018/01/03 Javascript
Vue-Router模式和钩子的用法
2018/02/28 Javascript
vue-cli3 项目从搭建优化到docker部署的方法
2019/01/28 Javascript
Vue 实现监听窗口关闭事件,并在窗口关闭前发送请求
2020/09/01 Javascript
布同自制Python函数帮助查询小工具
2011/03/13 Python
Python3.x和Python2.x的区别介绍
2013/02/12 Python
在Python中操作列表之list.extend()方法的使用
2015/05/20 Python
在Django中限制已登录用户的访问的方法
2015/07/23 Python
Django自定义分页与bootstrap分页结合
2021/02/22 Python
Python基于QRCode实现生成二维码的方法【下载,安装,调用等】
2017/07/11 Python
python cx_Oracle的基础使用方法(连接和增删改查)
2017/11/19 Python
Python实现查询某个目录下修改时间最新的文件示例
2018/08/29 Python
Tensorflow分类器项目自定义数据读入的实现
2019/02/05 Python
python导入坐标点的具体操作
2019/05/10 Python
ML神器:sklearn的快速使用及入门
2019/07/11 Python
python入门之井字棋小游戏
2020/03/05 Python
PyQt5如何将.ui文件转换为.py文件的实例代码
2020/05/26 Python
浅谈Python中的模块
2020/06/10 Python
Django使用django-simple-captcha做验证码的实现示例
2021/01/07 Python
健身场所或家用健身设备:Life Fitness
2017/11/01 全球购物
广州御银科技股份有限公司试卷(C++)
2016/11/04 面试题
PHP使用Redis队列执行定时任务实例讲解
2021/03/24 PHP
生物技术专业求职信
2014/06/10 职场文书
小学生关于梦想的演讲稿
2014/08/22 职场文书
初中教师个人工作总结
2015/02/10 职场文书
2016教师读书思廉心得体会
2016/01/23 职场文书