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 相关文章推荐
JavaScript在IE和Firefox(火狐)的不兼容问题解决方法小结
Apr 13 Javascript
高性能WEB开发 flush让页面分块,逐步呈现 flush让页面分块,逐步呈现
Jun 19 Javascript
ajax跨域调用webservice的实现代码
May 09 Javascript
30分钟快速掌握Bootstrap框架
May 24 Javascript
easyui form validate总是返回false的原因及解决方法
Nov 07 Javascript
wap手机端解决返回上一页的js实例
Dec 08 Javascript
javascript内存分配原理实例分析
Apr 10 Javascript
JS实现多物体运动的方法详解
Jan 23 Javascript
浅谈MUI框架中加载外部网页或服务器数据的方法
Jan 31 Javascript
vuex实现登录状态的存储,未登录状态不允许浏览的方法
Mar 09 Javascript
详解ES6通过WeakMap解决内存泄漏问题
Mar 09 Javascript
vue实现日历表格(element-ui)
Sep 24 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/08/18 PHP
IIS6.0中配置php服务全过程解析
2013/08/07 PHP
PHP程序员常见的40个陋习,你中了几个?
2014/11/20 PHP
yii使用bootstrap分页样式的实例
2017/01/17 PHP
php设计模式之中介者模式分析【星际争霸游戏案例】
2020/03/23 PHP
解javascript 混淆加密收藏
2009/01/16 Javascript
jQuery 版本的文本输入框检查器Input Check
2009/07/09 Javascript
jquery 学习之一 对象访问
2010/11/23 Javascript
jQuery学习笔记之Helloworld
2010/12/22 Javascript
离开当前页面前使用js判断条件提示是否要离开页面
2014/05/02 Javascript
浅谈JavaScript数据类型及转换
2015/02/28 Javascript
jquery实现根据浏览器窗口大小自动缩放图片的方法
2015/07/17 Javascript
Javascript的比较汇总
2016/07/25 Javascript
微信小程序 ecshop地址三级联动实现实例代码
2017/02/28 Javascript
原生javascript上传图片带进度条【实例分享】
2017/04/06 Javascript
javascript 的变量、作用域和内存问题
2017/04/19 Javascript
vue2 自定义动态组件所遇到的问题
2017/06/08 Javascript
深入浅析javascript函数中with
2018/10/28 Javascript
详解基于React.js和Node.js的SSR实现方案
2019/03/21 Javascript
微信小程序云开发之模拟后台增删改查
2019/05/16 Javascript
原生JS实现微信通讯录
2020/06/18 Javascript
从零开始用webpack构建一个vue3.0项目工程的实现
2020/09/24 Javascript
[57:18]DOTA2上海特级锦标赛主赛事日 - 1 败者组第一轮#3VP VS VG
2016/03/03 DOTA
轻松实现python搭建微信公众平台
2016/02/16 Python
python 第三方库的安装及pip的使用详解
2017/05/11 Python
python实现图书馆研习室自动预约功能
2018/04/27 Python
Python/Django后端使用PIL Image生成头像缩略图
2019/04/30 Python
python如何通过twisted搭建socket服务
2020/02/03 Python
解决import tensorflow as tf 出错的原因
2020/04/16 Python
AmazeUI 手机版页面的顶部导航条Header与侧边导航栏offCanvas的示例代码
2020/08/19 HTML / CSS
ProBikeKit德国:在线公路自行车专家
2018/06/03 全球购物
有机婴儿毛毯和衣服:Monica + Andy
2020/03/01 全球购物
报关员个人职业生涯规划书
2014/03/12 职场文书
《云雀的心愿》教学反思
2016/02/23 职场文书
用Python爬取各大高校并可视化帮弟弟选大学,弟弟直呼牛X
2021/06/11 Python
PostgreSQL出现死锁该如何解决
2022/05/30 PostgreSQL