前端学数据结构:栈和队列

本文首发于 个人 Githubgit

栈遵循 后进先出 的原则。github

/** * 栈 * 后进先出 */
class Stack {
  constructor() {
    this.items = [];
  }

  // 添加元素
  push(value) {
    this.items.push(value);
  }

  // 返回栈顶的元素
  peek() {
    return this.items[this.items.length - 1];
  }

  // 移出栈顶的元素
  pop() {
    return this.items.pop();
  }
  
  /** * 判断栈是否为空 */
  isEmpty() {
    return this.items.length <= 0;
  }
}
复制代码

队列

队列遵循 先进先出 的原则。this

/** * 队列 * 先进先出 */
class Queue {
  constructor() {
    this.items = [];
  }

  /** * 添加元素 */
  enqueue(value) {
    this.items.push(value);
  }

  /** * 移出队列的第一个元素 */
  dequeue() {
    return this.items.shift();
  }
}
复制代码

常见题目

1. 有效的括号

问题描述

给定一个只包括 '(',')','{','}','[',']'的字符串,判断字符串是否有效。spa

解题思路

使用 来解决。code

  • 遍历字符串,若是是左括号便压入栈中。
  • 若是遇到右括号,分类谈论:
    1. 若是当前栈为空,返回 false
    2. 取出栈顶元素,若是与之匹配继续循环,不然返回 false
/** * 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。 * @param {*} str */
function isValidStr(str) {
  let arr = str.split("");
  let stack = new Stack();

  function isMatchStr(a, b) {
    return (
      (a === "(" && b === ")") ||
      (a === "[" && b === "]") ||
      (a === "{" && b === "}")
    );
  }

  while (arr.length) {
    let char = arr.shift();

    if (char === "(" || char === "[" || char === "{") {
      stack.push(char);
    } else {
      if (stack.isEmpty()) {
        return false;
      } else if (isMatchStr(stack.pop(), char)) {
        continue;
      } else {
        return false;
      }
    }
  }

  return true;
}
复制代码

2. 用两个栈实现队列

问题描述

用两个栈来实现一个队列,完成队列的 enqueuedequeue 操做。队列

解题思路

in 栈用于处理 入列 操做,out 栈用于处理 出列 操做。字符串

  • 入列的值直接压入 in
  • 出列时,将 in 栈的元素出栈压入到 out 栈,而后返回 out 栈栈顶的元素(这样便保持了队列 先进先出 的原则)。
class TwoStackQueue {
  constructor() {
    this.inStack = new Stack();
    this.outStack = new Stack();
  }

  enqueue(value) {
    this.inStack.push(value);
  }

  dequeue() {
    while (!this.inStack.isEmpty()) {
      this.outStack.push(this.inStack.pop());
    }

    return this.outStack.pop();
  }
}
复制代码

3. 栈的压入、弹出序列

问题描述

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的全部数字均不相等。例如序列 1,2,3,4,5 是某栈的压入顺序,序列 4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不多是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)get

解题思路

初始化一个辅助栈,遍历压入顺序,执行入栈操做,入栈的同时,若是辅助栈非空,同时弹出序列的当前值与辅助栈栈顶元素相同,则辅助栈出栈。最后判断辅助是否为空,为空这是正确的顺序,不然不是。例如:string

入栈:1, 2, 3, 4, 5
出栈:4, 5, 3, 2, 1
it

首先,1 入栈,此时栈顶元素 1 != 4,继续入栈;
2 != 4,入栈;
3 != 4 入栈;
4 == 4,入栈后出栈(这时候栈内元素为 1, 2, 3);
3 != 5,入栈(这时候栈内元素为 1, 2, 3, 5),5 == 5 出栈,3 == 3 出栈...
最后栈为空,顺序匹配。

function isPopOrder(pushOrder, popOrder) {
  let stack = new Stack();
  let popIndex = 0;

  for (let pushIndex = 0; pushIndex < pushOrder.length; pushIndex++) {
    stack.push(pushOrder[pushIndex]);

    while (!stack.isEmpty() && stack.peek() === popOrder[popIndex]) {
      stack.pop();
      popIndex++;
    }
  }

  return stack.isEmpty();
}
复制代码
相关文章
相关标签/搜索