数据结构与算法JavaScript描述笔记3 - 栈

119 阅读2分钟
  • 定义:栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端称为栈顶。栈被称为一种后入先出(LIFO, last-in-first-out)的数据结构。
  • 对栈的两种主要操作是将一个元素压入栈和将一个元素弹出栈。入栈使用push()方法,出栈使用pop()方法。
  • pop()方法虽然可以访问栈顶的元素,但是调用该方法后,栈顶元素也从栈中被永久性地删除了。peek()方法则只返回栈顶元素,而不删除它。
  • push()、pop()和peek()是栈的3个主要方法,clear()方法清除栈内所有元素,length属性记录栈内元素的个数。empty属性,用以表示栈内是否含有元素,使用length属性也可以达到同样的目的。
  • 具体实现:
      function Stack() {
          this.dataStore = [];
          this.top = 0;
          this.push = function(element) {
              this.dataStore[this.top++] = element;
          }
          this.pop = function() {
              return this.dataStore[--this.top];
          }
          this.peek = function() {
              return this.dataStore[this.top-1];
          }
          this.length = function() {
              return this.top;
          }
          this.clear = function() {
              this.top = 0;
          }
      }
    
  • 应用
    • 数制间的相互转换

      算法:假设将数字n转换为以b为基数得数字(基数为2~9)

      1. 最高位为n%b,将此位压入栈;
      2. 使用n/b代替n;
      3. 重复步骤1和2,直到n等于0,且没有余数;
      4. 持续将栈内元素弹出,直到栈为空,依次将这些元素排列,就得到转换后数字得字符串形式。
      function mulBase(num, base) {
          var s = new Stack();
          do {
              s.push(num % base);
              num = Math.floor( num / base );
          } while (num > 0);
          var converted = '';
          while (s.length() > 0) {
              converted += s.pop();
          }
          return converted;
      }
      
    • 使用栈模拟递归
      求阶乘函数的递归:5!= 5 * 4 * 3 * 2 * 1 = 120
      递归函数:

      function factorial(n) {
          if (n === 0) {
              return 1;
          } else {
              return n * factorial(n-1)
          }
      }
      

      使用栈模拟递归:

      function fact(n) {
          var s = new Stack();
          while (n > 1) {
              s.push(n--);
          }
          var product = 1;
          while (s.length() > 0) {
              product *= s.pop()
          }
          return product;
      }
      

练习

  • 栈可以用来判断一个表达式中得括号是否匹配。编写一个函数,该函数接受一个算数表达式作为参数,返回括号缺失的位置。下面是一个括号不匹配得算术表达式:2.3+23/12 +(3.14159*0.24
    扫描表达式,遇到左括号时进栈,遇到右括号时若栈顶为左括号,则出栈
      function matchBracket (str) {
          var index = -1;
          var s = new Stack();
          var left = ['(', '{', '['];
          var right = [')', '}', ']'];
          for(let i = 0; i < str.length; i++) {
              if (left.includes(str[i])) {
                  s.push(str[i])
              } else if (right.includes(str[i])) {
                  // 获取栈顶元素
                  var c = s.peek();
                  switch(str[i]) {
                      case '}':
                        if (c === '{') {
                            s.pop();
                            breack;
                        }
                        return i + 1;
                      case ']':
                        if (c === '[') {
                            s.pop();
                            break;
                        }
                        return i + 1;
                      case ')':
                        if (c === '(') {
                            s.pop();
                            break;
                        }
                        return i + 1;
                      default: break;
                  }
              }
          }
          return s.length() > 0 ? str.length + 1 : -1;
      }
      console.log(matchBracket('2+[3/1+(3*2]'))  // 12