数组是常用的数据结构,尽管可以在数组的任意位置上删除或添加元素。然而,有时我们还需要一种在添加或删除元素时有更多控制的数据结构。有两种类似于数组但是更为可控的数据类型,称之为栈和队列。
栈
栈是一种遵从后进先出(LIFO)原则的有序集合。新添加的或待删除的元素都保存在栈的同一端,称作栈顶,另一端为栈底。在栈里,新元素都靠近栈顶,旧元素都接近栈底。
创建栈
一个栈类需要有如下几个方法:
push(element(s)):添加一个(或几个)新元素到栈顶。pop():移除栈顶的元素,同时返回被移除的元素。peek():返回栈顶的元素,不对栈做任何修改。isEmpty():如果栈里没有任何元素就返回true,否则返回false。clear():移除栈里的所有元素。size():返回栈里的元素个数。与数组的length属性类似。
尽管ES6引入了类的语法,由于js本身并没有私有变量这个概念,所以创建的栈相当容易被外部修改。
用栈解决问题
1. 进制转换

十进制转二进制的方法:使用十进制的数据不断除以2,直到商为0为止,从下往上取余就是对应的二进制。
我们可以将每一次的余数传入栈中,当计算结束时,再将栈内的所有余数按顺序取出,连接为字符串,即为传入参数的二进制形式。
1  | /**  | 
经过测试后,可以发现这个函数可以正确转化十进制为二进制。
而在这个函数的基础之上,我们还可以将这个函数改造为高阶函数,使其可以返回十进制以下的任意进制。
1  | 
  | 
将上述代码在控制台输出,可以发现结果正确为
10-->1010,之所以只能转化为十以下的进制是因为,一共只有0~9这10个数字,超过十进制之后需要用大写字母表示10及以上的数字。10—A,11—B,12—C,13—D…
2. 平衡括号
在编程过程中,括号必须是平衡的。平衡括号的意思是,每个左括号一定对应着一个右括号,括号内又套着括号。看下面这些个括号组成的平衡表达式:
1  | (()()()())  | 
对比下面这些不平衡的括号:1
2
3
4
5((((((())
()))
(()()(()
正确地区分平衡和不平衡括号,对很多编程语言来说,都是重要的内容。
在js中一共会使用到3种括号:[]、{}、()
那么现在有个问题,如何判断一段括号字符串的括号是否平衡。
仔细观察一下平衡式的结构特点。当从左到右读入一串括号的时候,最早读到的一个右括号总是与他前面的紧邻的左括号匹配,同样,最后一个右括号要与最先读到的左括号相匹配。即右括号与左括号是反序的,它们从内到外一一匹配,这就给我们启示,可以用栈来解决问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25function parenthesesChecker(symbols) {
  const stack = new Stack();
  const opens = '([{';
  const closers = ')]}';
  let balanced = true;
  let index = 0;
  let symbol;
  let top;
  while (index < symbols.length && balanced) {
    symbol = symbols[index];
    if (opens.indexOf(symbol) >= 0) {
      stack.push(symbol);
    } else if (stack.isEmpty()) {
      balanced = false;
    } else {
      top = stack.pop();
      if (!(opens.indexOf(top) === closers.indexOf(symbol))) {
        balanced = false;
      }
    }
    index++;
  }
  return balanced && stack.isEmpty();
}
这个函数首先创建了opens和closers这两个变量,将括号拆分为左右两个集合,且位置一一对应,用作之后的对照判断,balanced做为是否平衡的判断,以此来作为控制while循环条件的一部分。
进入循环后,将传入的括号字符串第
index个字符取出,做为变量symbol的值。index初始值为0,在while循环中累加
首先判断,
symbol是否存在于opens中,如果存在,将symbol存入栈中。|– 如果不存在,表示
symbol为右半边括号,当栈为空,即栈中没有左半边与之对应,则括号必然不平衡,将balanced设为false,中止循环。symbol为右半边括号,当栈中存有左半部分括号时,将栈顶的括号取出,与symbol比较,判断是否对应:|—
opens.indexOf(top) === closers.indexOf(symbol)为true时,继续循环。index++|—否则,将
balanced设为false,中止循环。
.
.
.- 循环结束后返回结果