• 基于JavaScript实现的栈数据结构
  • 发布于 1周前
  • 27 热度
    0 评论
栈(Stack)是一种常见且重要的数据结构,它遵循后进先出(LIFO)的原则,即最后入栈的元素最先出栈。栈在计算机科学中应用广泛,例如函数调用栈、表达式求值、浏览器历史记录等。

一、栈的基本操作
栈通常支持以下基本操作:
push(element): 将元素压入栈顶。
pop(): 移除并返回栈顶元素。
peek(): 返回栈顶元素,但不移除它。
isEmpty(): 判断栈是否为空。
size(): 返回栈中元素的个数。
clear(): 清空栈。

二、使用数组实现栈
在 JavaScript 中,我们可以使用数组来模拟栈的行为。数组的 push() 和 pop() 方法正好对应栈的入栈和出栈操作。
class Stack {
constructor() {
    this.items = [];
  }

// 入栈
  push(element) {
    this.items.push(element);
  }

// 出栈
  pop() {
    if (this.isEmpty()) {
      return"Stack is empty";
    }
    returnthis.items.pop();
  }

// 查看栈顶元素
  peek() {
    if (this.isEmpty()) {
      return"Stack is empty";
    }
    returnthis.items[this.items.length - 1];
  }

// 判断栈是否为空
  isEmpty() {
    returnthis.items.length === 0;
  }

// 返回栈的大小
  size() {
    returnthis.items.length;
  }

// 清空栈
  clear() {
    this.items = [];
  }
}
// 堆代码 duidaima.com
// 测试代码
const stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
console.log(stack.peek()); // 3
console.log(stack.pop());  // 3
console.log(stack.size()); // 2
stack.clear();
console.log(stack.isEmpty()); // true
三、栈的应用场景
1. 函数调用栈
JavaScript 引擎使用栈来管理函数调用。每次调用函数时,都会创建一个新的栈帧并将其压入栈顶。栈帧中存储了函数的局部变量、参数和返回地址等信息。当函数执行完毕后,其对应的栈帧会被弹出,程序继续执行上一个栈帧中的代码。

2. 括号匹配
栈可以用来检查表达式中的括号是否匹配。例如,我们可以遍历表达式,遇到左括号就入栈,遇到右括号就出栈并检查是否匹配。
function isBalanced(expression) {
const stack = new Stack();
const brackets = { "(": ")", "{": "}", "[": "]" };

for (let char of expression) {
    if (brackets[char]) {
      stack.push(char);
    } elseif (Object.values(brackets).includes(char)) {
      if (stack.isEmpty() || brackets[stack.pop()] !== char) {
        returnfalse;
      }
    }
  }
return stack.isEmpty();
}

console.log(isBalanced("({[]})")); // true
console.log(isBalanced("({[})"));  // false
3. 进制转换
栈可以用来将十进制数转换为其他进制数。例如,我们可以不断地将十进制数除以目标进制,并将余数入栈,最后将栈中的元素依次弹出即可得到结果。
function baseConverter(decNumber, base) {
const stack = new Stack();
const digits = "0123456789ABCDEF";

while (decNumber > 0) {
    stack.push(decNumber % base);
    decNumber = Math.floor(decNumber / base);
  }

let result = "";
while (!stack.isEmpty()) {
    result += digits[stack.pop()];
  }

return result || "0";
}
console.log(baseConverter(100, 2));  // 1100100
console.log(baseConverter(100, 8));  // 144
console.log(baseConverter(100, 16)); // 64
4. 深度优先搜索(DFS)
在图和树的遍历算法中,深度优先搜索(DFS)是一种常见的方法。DFS 使用栈来存储待访问的节点,从而实现深度优先的遍历。
class Graph {
constructor() {
    this.adjacencyList = newMap();
  }

  addVertex(vertex) {
    this.adjacencyList.set(vertex, []);
  }

  addEdge(vertex1, vertex2) {
    this.adjacencyList.get(vertex1).push(vertex2);
    this.adjacencyList.get(vertex2).push(vertex1);
  }

  dfs(startVertex) {
    const stack = new Stack();
    const visited = newSet();

    stack.push(startVertex);
    visited.add(startVertex);

    while (!stack.isEmpty()) {
      const currentVertex = stack.pop();
      console.log(currentVertex);

      for (const neighbor ofthis.adjacencyList.get(currentVertex)) {
        if (!visited.has(neighbor)) {
          stack.push(neighbor);
          visited.add(neighbor);
        }
      }
    }
  }
}

// 测试代码
const graph = new Graph();
graph.addVertex('A');
graph.addVertex('B');
graph.addVertex('C');
graph.addVertex('D');
graph.addEdge('A', 'B');
graph.addEdge('A', 'C');
graph.addEdge('B', 'D');
graph.addEdge('C', 'D');

graph.dfs('A'); // A, C, D, B
四、总结
通过理解栈的基本操作和应用场景,我们可以更好地利用它来解决实际问题。除了数组,我们还可以使用链表等其他数据结构来实现栈。不同的实现方式各有优缺点,需要根据具体场景进行选择。
用户评论