- 定义:栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端称为栈顶。栈被称为一种后入先出(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)
- 最高位为n%b,将此位压入栈;
- 使用n/b代替n;
- 重复步骤1和2,直到n等于0,且没有余数;
- 持续将栈内元素弹出,直到栈为空,依次将这些元素排列,就得到转换后数字得字符串形式。
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