返回

React 源码中的非递归先序和后序遍历算法

前端

React 源码中非递归先序遍历和后序遍历算法

计算机科学中,树的遍历算法是数据结构课程的基础。掌握先序遍历和后序遍历对理解 React 内部流程非常有帮助,例如 React 调和阶段就是先序遍历。

先序遍历

先序遍历按照根节点、左子树、右子树的顺序遍历树。使用非递归算法实现先序遍历的步骤如下:

  1. 将根节点压入栈中。
  2. 只要栈不为空,执行以下步骤:
    • 弹出栈顶元素并访问它。
    • 如果该元素有右子树,将右子树压入栈中。
    • 如果该元素有左子树,将左子树压入栈中。

代码示例:

function preorderTraversal(root) {
  if (!root) return;
  const stack = [root];
  while (stack.length) {
    const node = stack.pop();
    console.log(node.val);
    if (node.right) stack.push(node.right);
    if (node.left) stack.push(node.left);
  }
}

后序遍历

后序遍历按照左子树、右子树、根节点的顺序遍历树。使用非递归算法实现后序遍历的步骤如下:

  1. 创建一个栈和一个上一次访问的节点变量。
  2. 将根节点压入栈中。
  3. 只要栈不为空,执行以下步骤:
    • 将栈顶元素设为当前节点。
    • 如果当前节点没有被访问过或其右子树已经被访问过,访问当前节点。
    • 否则,将当前节点的右子树压入栈中。
    • 将当前节点的左子树压入栈中。
    • 设置上一次访问的节点为当前节点。

代码示例:

function postorderTraversal(root) {
  if (!root) return;
  const stack = [root];
  let prev = null;
  while (stack.length) {
    const node = stack[stack.length - 1];
    if (!prev || prev.left === node || prev.right === node) {
      if (node.left) stack.push(node.left);
      else if (node.right) stack.push(node.right);
      else {
        stack.pop();
        console.log(node.val);
      }
    } else if (node.left === prev) {
      if (node.right) stack.push(node.right);
      else {
        stack.pop();
        console.log(node.val);
      }
    } else {
      stack.pop();
      console.log(node.val);
    }
    prev = node;
  }
}

结论

非递归先序遍历和后序遍历算法对于理解 React 源码中的树遍历操作至关重要。这些算法使用栈数据结构,在执行过程中高效地遍历树。掌握这些算法有助于我们深入了解 React 的内部机制和优化技巧。