二叉樹遍歷方法總結

一杯綠茶發表於2021-09-26

深度優先遍歷

1) 前序遍歷

遞迴實現:

const preOrder = (root) => {
  let result = [];
  const traverseNode = (node) => {
    if (node) {
      // 先根節點
      result.push(node.val);
      // 然後遍歷左子樹
      traverseNode(node.left);
      // 再遍歷右子樹
      traverseNode(node.right);
    }
  }
  traverseNode(root);
  return result;
}

非遞迴實現:

const preOrder = (root) => {
  let list = [];
  let stack = [];
  // 當根節點不為空的時候,將根節點入棧
  if (root != null) stack.push(root);
  while (stack.length > 0) {
    root = stack.pop();
    // 先訪問根節點
    list.push(root.val);
    // 我們先列印左子樹,然後右子樹
    // 所以先入棧的是右子樹,然後左子樹
    if (root.right != null) stack.push(root.right);
    if (root.left != null) stack.push(root.left);
  }
  return list;
}

2) 中序遍歷

遞迴實現:

const inOrder = (root) => {
  let result = [];
  const traverseNode = (node) => {
    if (node) {
      // 先遍歷左子樹
      traverseNode(node.left);
      // 然後根節點
      result.push(node.val);
      // 再遍歷右子樹
      traverseNode(node.right);
    }
  }
  traverseNode(root);
  return result;
}

非遞迴實現:

const inOrder = (root) => {
  let list = [];
  let stack = [];
  while (stack.length > 0 || root != null) {
    if (root != null) {
      // 如果當前節點非空,就將當前節點入棧
      stack.push(root);
      // 指標向當前節點的左節點方向移動
      root = root.left;
    } else {
      // 當前節點為空,則從棧頂彈出元素
      root = stack.pop();
      list.push(root.val);
      // 指標向右節點方向移動
      root = root.right;
    }
  }
  return list;
}

3) 後序遍歷

遞迴實現:

const postOrder = (root) => {
  let result = [];
  const traverseNode = (node) => {
    if (node) {
      // 先遍歷左子樹
      traverseNode(node.left);
      // 然後遍歷右子樹
      traverseNode(node.right);
      // 最後根節點
      result.push(node.val);
    }
  }
  traverseNode(root);
  return result;
}

非遞迴實現:

const postOrder = (root) => {
  let list = [];
  let stack = [];
  // 當根節點不為空,將根節點入棧
  if (root != null) stack.push(root);
  while (stack.length > 0) {
    root = stack.pop();
    // 由於後序遍歷輸出順序是:左=>右=>根
    // 先將新增結果的順序反一下
    list.unshift(root.val);
    // 然後讓左子樹先入棧,後右子樹
    // 這樣出棧順序就變成先右後左
    if (root.left != null) stack.push(root.left);
    if (root.right != null) stack.push(root.right);
  }
  return list;
}

廣度優先遍歷 (層序遍歷)

非遞迴實現:

const levelOrder = (root) => {
  let list = [];
  let queue = [];
  if (root != null) queue.push(root);
  while (queue.length > 0) {
    let size = queue.length;
    let temp = [];
    for (let i=0; i<size; i++) {
      // 將當前佇列元素全部出隊
      root = queue.pop();
      // 將結果新增到陣列中
      temp.push(root.val);
      // 然後將下一層的元素加入佇列
      if (root.right != null) queue.push(root.right);
      if (root.left != null) queue.push(root.left);
    }
    list.push(temp);
  }
  return list;
}

相關文章