树和图最大的差别就是看有没有环。
Linked List 是特殊化的 Tree,Tree 是特殊化的 Graph。
二叉树遍历 Pre-order/In-order/Post-order。
- 前序(Pre-order):根-左-右
- 中序(In-order):左-根-右
- 后序(Post-order):左-右-根
二叉树遍历可以使用递归或者栈的方式解决。
// 前序遍历const preorder = (root) => {if (!root) return;console.log(root.val);preorder(root.left);preorder(root.right);}const preorder = (root) => {if (!root) return;const stack = [root];while (stack.length) {const n = stack.pop();console.log(n.val);if (n.right) stack.push(n.right);if (n.left) stack.push(n.left);}}
// 中序遍历const inorder = (root) => {if (!root) return;inorder(root.left);console.log(root.val);inorder(root.right);}const inorder = (root) => {if (!root) return;const stack = [];let p = root;while (stack.length || p) {while (p) {stack.push(p);p = p.left;}const n = stack.pop();console.log(n.val);p = n.right;}}
// 后序遍历const postorder = (root) => {if (!root) return;postorder(root.left);postorder(root.right);console.log(root.val);}const postorder = (root) => {if (!root) return;const outputStack = [];const stack = [root];while (stack.length) {const n = stack.pop();outputStack.push(n);if (n.left) stack.push(n.left);if (n.right) stack.push(n.right);}while (outputStack.length) {const n = outputStack.pop();console.log(n.val);}}
普通的树遍历的话都是 O(n) 的时间复杂度,和链表没有太大区别。
二叉搜索树(Binary Search Tree),也称二叉排序树、有序二叉树(Ordered Binary Tree)、排序二叉树(Sorted Binary Tree),是指一棵空树或者具有下列性质的二叉树。
- 左子树上所有结点的值均小于它的根结点的值
- 右子树上所有结点的值均大于它的根结点的值
- 以此类推:左、右子树也分别为二叉查找树
中序遍历:升序排列
二叉搜索树的时间复杂度是 O(log n),极端情况下会退化到 O(n)。
二叉搜索树查询、插入、删除 Demo 演示: https://visualgo.net/zh/bst
二叉树的中序遍历(亚马逊、微软、字节跳动在半年内面试中考过)
二叉树的前序遍历(谷歌、微软、字节跳动在半年内面试中考过)
N 叉树的后序遍历(亚马逊在半年内面试中考过)
N 叉树的前序遍历(亚马逊在半年内面试中考过)
// 二叉树的中序遍历// 思路1:递归解法,复杂度 O(n)// 思路2:迭代解法,维护一个栈,复杂度 O(n)/*** @param {TreeNode} root* @return {number[]}*/var inorderTraversal = function(root) {if (!root) return [];const res = [];const inorder = (root) => {root.left && inorder(root.left);res.push(root.val);root.right && inorder(root.right);}inorder(root);return res;};/*** @param {TreeNode} root* @return {number[]}*/var inorderTraversal = function(root) {const res = [];const stack = [];while (root || stack.length) {while (root) {stack.push(root);root = root.left;}root = stack.pop();res.push(root.val);root = root.right;}return res;};
// 二叉树的前序遍历/*** @param {TreeNode} root* @return {number[]}*/var preorderTraversal = function(root) {if (!root) return [];const res = [];const preorder = (root) => {res.push(root.val);root.left && preorder(root.left);root.right && preorder(root.right);}preorder(root);return res;};/*** @param {TreeNode} root* @return {number[]}*/var preorderTraversal = function(root) {if (!root) return [];const stack = [root];const res = [];while (stack.length) {const curr = stack.pop();res.push(curr.val);curr.right && stack.push(curr.right);curr.left && stack.push(curr.left);}return res;};
// N 叉树的后序遍历/*** @param {Node|null} root* @return {number[]}*/var postorder = function(root) {if (!root) return [];const res = [];const _postorder = (root) => {root.children && root.children.forEach(_postorder);res.push(root.val);}_postorder(root);return res;};/*** @param {Node|null} root* @return {number[]}*/var postorder = function(root) {if (!root) return [];const res = [];const stack = [root];while (stack.length) {const curr = stack.pop();res.push(curr.val);curr.children && stack.push(...curr.children);}return res.reverse();};
// N 叉树的前序遍历/*** @param {Node|null} root* @return {number[]}*/var preorder = function(root) {if (!root) return [];const res = [];const _preorder = (root) => {res.push(root.val);root.children && root.children.forEach(_preorder);}_preorder(root);return res;};/*** @param {Node|null} root* @return {number[]}*/var preorder = function(root) {if (!root) return [];const res = [];const stack = [root];while (stack.length) {const curr = stack.pop();res.push(curr.val);curr.children && stack.push(...curr.children.reverse());}return res;};
// N 叉树的层序遍历/*** @param {Node|null} root* @return {number[][]}*/var levelOrder = function(root) {if (!root) return [];const res = [];const _levelorder = (root, level) => {res[level] ? res[level].push(root.val) : res[level] = [root.val];root.children && root.children.forEach(curr => _levelorder(curr, level + 1));}_levelorder(root, 0);return res;};/*** @param {Node|null} root* @return {number[][]}*/var levelOrder = function(root) {if (!root) return [];const res = [];const queue = [root];while (queue.length) {const len = queue.length;const level = [];for (let i = 0; i < len; i++) {const curr = queue.shift();level.push(curr.val);queue.push(...curr.children);}res.push(level);}return res;};
