树和图最大的差别就是看有没有环。

    Linked List 是特殊化的 Tree,Tree 是特殊化的 Graph。

    二叉树遍历 Pre-order/In-order/Post-order。

    • 前序(Pre-order):根-左-右
    • 中序(In-order):左-根-右
    • 后序(Post-order):左-右-根

    二叉树遍历可以使用递归或者栈的方式解决。

    1. // 前序遍历
    2. const preorder = (root) => {
    3. if (!root) return;
    4. console.log(root.val);
    5. preorder(root.left);
    6. preorder(root.right);
    7. }
    8. const preorder = (root) => {
    9. if (!root) return;
    10. const stack = [root];
    11. while (stack.length) {
    12. const n = stack.pop();
    13. console.log(n.val);
    14. if (n.right) stack.push(n.right);
    15. if (n.left) stack.push(n.left);
    16. }
    17. }
    1. // 中序遍历
    2. const inorder = (root) => {
    3. if (!root) return;
    4. inorder(root.left);
    5. console.log(root.val);
    6. inorder(root.right);
    7. }
    8. const inorder = (root) => {
    9. if (!root) return;
    10. const stack = [];
    11. let p = root;
    12. while (stack.length || p) {
    13. while (p) {
    14. stack.push(p);
    15. p = p.left;
    16. }
    17. const n = stack.pop();
    18. console.log(n.val);
    19. p = n.right;
    20. }
    21. }
    1. // 后序遍历
    2. const postorder = (root) => {
    3. if (!root) return;
    4. postorder(root.left);
    5. postorder(root.right);
    6. console.log(root.val);
    7. }
    8. const postorder = (root) => {
    9. if (!root) return;
    10. const outputStack = [];
    11. const stack = [root];
    12. while (stack.length) {
    13. const n = stack.pop();
    14. outputStack.push(n);
    15. if (n.left) stack.push(n.left);
    16. if (n.right) stack.push(n.right);
    17. }
    18. while (outputStack.length) {
    19. const n = outputStack.pop();
    20. console.log(n.val);
    21. }
    22. }

    普通的树遍历的话都是 O(n) 的时间复杂度,和链表没有太大区别。

    二叉搜索树(Binary Search Tree),也称二叉排序树、有序二叉树(Ordered Binary Tree)、排序二叉树(Sorted Binary Tree),是指一棵空树或者具有下列性质的二叉树。

    • 左子树上所有结点的值均小于它的根结点的值
    • 右子树上所有结点的值均大于它的根结点的值
    • 以此类推:左、右子树也分别为二叉查找树

    中序遍历:升序排列

    二叉搜索树的时间复杂度是 O(log n),极端情况下会退化到 O(n)。

    二叉搜索树查询、插入、删除 Demo 演示: https://visualgo.net/zh/bst

    二叉树的中序遍历(亚马逊、微软、字节跳动在半年内面试中考过)

    二叉树的前序遍历(谷歌、微软、字节跳动在半年内面试中考过)

    N 叉树的后序遍历(亚马逊在半年内面试中考过)

    N 叉树的前序遍历(亚马逊在半年内面试中考过)

    N 叉树的层序遍历

    1. // 二叉树的中序遍历
    2. // 思路1:递归解法,复杂度 O(n)
    3. // 思路2:迭代解法,维护一个栈,复杂度 O(n)
    4. /**
    5. * @param {TreeNode} root
    6. * @return {number[]}
    7. */
    8. var inorderTraversal = function(root) {
    9. if (!root) return [];
    10. const res = [];
    11. const inorder = (root) => {
    12. root.left && inorder(root.left);
    13. res.push(root.val);
    14. root.right && inorder(root.right);
    15. }
    16. inorder(root);
    17. return res;
    18. };
    19. /**
    20. * @param {TreeNode} root
    21. * @return {number[]}
    22. */
    23. var inorderTraversal = function(root) {
    24. const res = [];
    25. const stack = [];
    26. while (root || stack.length) {
    27. while (root) {
    28. stack.push(root);
    29. root = root.left;
    30. }
    31. root = stack.pop();
    32. res.push(root.val);
    33. root = root.right;
    34. }
    35. return res;
    36. };
    1. // 二叉树的前序遍历
    2. /**
    3. * @param {TreeNode} root
    4. * @return {number[]}
    5. */
    6. var preorderTraversal = function(root) {
    7. if (!root) return [];
    8. const res = [];
    9. const preorder = (root) => {
    10. res.push(root.val);
    11. root.left && preorder(root.left);
    12. root.right && preorder(root.right);
    13. }
    14. preorder(root);
    15. return res;
    16. };
    17. /**
    18. * @param {TreeNode} root
    19. * @return {number[]}
    20. */
    21. var preorderTraversal = function(root) {
    22. if (!root) return [];
    23. const stack = [root];
    24. const res = [];
    25. while (stack.length) {
    26. const curr = stack.pop();
    27. res.push(curr.val);
    28. curr.right && stack.push(curr.right);
    29. curr.left && stack.push(curr.left);
    30. }
    31. return res;
    32. };
    1. // N 叉树的后序遍历
    2. /**
    3. * @param {Node|null} root
    4. * @return {number[]}
    5. */
    6. var postorder = function(root) {
    7. if (!root) return [];
    8. const res = [];
    9. const _postorder = (root) => {
    10. root.children && root.children.forEach(_postorder);
    11. res.push(root.val);
    12. }
    13. _postorder(root);
    14. return res;
    15. };
    16. /**
    17. * @param {Node|null} root
    18. * @return {number[]}
    19. */
    20. var postorder = function(root) {
    21. if (!root) return [];
    22. const res = [];
    23. const stack = [root];
    24. while (stack.length) {
    25. const curr = stack.pop();
    26. res.push(curr.val);
    27. curr.children && stack.push(...curr.children);
    28. }
    29. return res.reverse();
    30. };
    1. // N 叉树的前序遍历
    2. /**
    3. * @param {Node|null} root
    4. * @return {number[]}
    5. */
    6. var preorder = function(root) {
    7. if (!root) return [];
    8. const res = [];
    9. const _preorder = (root) => {
    10. res.push(root.val);
    11. root.children && root.children.forEach(_preorder);
    12. }
    13. _preorder(root);
    14. return res;
    15. };
    16. /**
    17. * @param {Node|null} root
    18. * @return {number[]}
    19. */
    20. var preorder = function(root) {
    21. if (!root) return [];
    22. const res = [];
    23. const stack = [root];
    24. while (stack.length) {
    25. const curr = stack.pop();
    26. res.push(curr.val);
    27. curr.children && stack.push(...curr.children.reverse());
    28. }
    29. return res;
    30. };
    1. // N 叉树的层序遍历
    2. /**
    3. * @param {Node|null} root
    4. * @return {number[][]}
    5. */
    6. var levelOrder = function(root) {
    7. if (!root) return [];
    8. const res = [];
    9. const _levelorder = (root, level) => {
    10. res[level] ? res[level].push(root.val) : res[level] = [root.val];
    11. root.children && root.children.forEach(curr => _levelorder(curr, level + 1));
    12. }
    13. _levelorder(root, 0);
    14. return res;
    15. };
    16. /**
    17. * @param {Node|null} root
    18. * @return {number[][]}
    19. */
    20. var levelOrder = function(root) {
    21. if (!root) return [];
    22. const res = [];
    23. const queue = [root];
    24. while (queue.length) {
    25. const len = queue.length;
    26. const level = [];
    27. for (let i = 0; i < len; i++) {
    28. const curr = queue.shift();
    29. level.push(curr.val);
    30. queue.push(...curr.children);
    31. }
    32. res.push(level);
    33. }
    34. return res;
    35. };