算法练习day12

33 阅读3分钟

一、二叉树理论基础

二叉树的种类

满二叉树

一个二叉树只有度为 0 或度为 2 的节点,并且度为 0 的节点都在同一层上,深度为 k,有 2^k - 1 个节点

完全二叉树

除了最底层没有填满,其余层的节点都填满,并且最底层的节点都集中在最左边,最底层,有 1 到 2^(k - 1)个节点

二叉搜索树

二叉搜索树是一个有序树,如果左子树不为空,则左子树上的所有节点的值均小于根节点的值,如果右子树不为空,则右子树上的所有节点的值均大于根节点的值,左右子树也均为二叉搜索树

平衡二叉搜索树

一个空树或者左右子树的高度差不超过 1,并且左右子树都是平衡二叉搜索树

二叉树的存储方式

链式存储

用指针,节点内存地址通过指针链接

顺序存储

用数组,内存地址连续,父节点的索引为 i,左子结点的索引为2 * i+ 1,右子节点的索引为2 * i + 2

二叉树的遍历方式

深度优先遍历

先往深走,遇到叶子节点再往回走

包括以下三种,主要根据中间节点的顺序判断

前序遍历,中左右

中序遍历,左中右

后序遍历,左右中

广度优先遍历

一层一层的遍历

function TreeNode(val = 0, left = null, right = null) {
  this.val = val;
  this.left = left;
  this.right = right;
}

二、递归遍历

前序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function (root) {
  let result = [];
  function dfs(root) {
    if (!root) {
      return;
    }
    result.push(root.val);
    dfs(root.left);
    dfs(root.right);
  }
  dfs(root);
  return result;
};

后序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
    let result = []
    function dfs(root) {
        if(!root) {
            return
        }
        dfs(root.left)
        dfs(root.right)
        result.push(root.val)
    }
    dfs(root)
    return result
};

中序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
    let result = []
    function dfs(root) {
        if(!root) {
            return
        }
        dfs(root.left)
        result.push(root.val)
        dfs(root.right)
    }
    dfs(root)
    return result
};

三、迭代遍历

前序遍历

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

中序遍历

var inorderTraversal = function(root) {
    if(!root) {
        return []
    }
    let result = []
    let stack = []
    let cur = root
    while(stack.length || cur) {
        if(cur) {
            stack.push(cur)
            cur = cur.left
        } else {
            let node = stack.pop()
            result.push(node.val)
            cur = node.right
        }
    }

    return result
};

后续遍历

var postorderTraversal = function(root) {
    let result = []
    let stack = []
    let cur = root
    let prev = null
    while(stack.length || cur) {
        if(cur) {
            stack.push(cur)
            cur = cur.left
        } else {
            let node = stack.pop()
            if(!node.right || node.right === prev) {
                result.push(node.val)
                prev = node
                cur = null
            } else {
                stack.push(node)
                cur = node.right
            }
        }
    }
    return result
};

四、统一迭代

标记法

前序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function (root) {
    let result = []
    let stack = []
    if (root) {
        stack.push(root)
    }
    while (stack.length) {
        let node = stack.pop()
        if (!node) {
            result.push(stack.pop().val)
            continue
        }
        if (node.right) {
            stack.push(node.right)
        }
        if (node.left) {
            stack.push(node.left)
        }
        stack.push(node)
        stack.push(null)

    }
    return result
};

中序遍历

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
    let stack = []
    let result = []
    if(root) {
        stack.push(root)
    }
    while(stack.length) {
        let node = stack.pop()
        if(!node) {
            result.push(stack.pop().val)
            continue
        }
        if(node.right) {
            stack.push(node.right)
        }
        stack.push(node)
        stack.push(null)
        if(node.left) {
            stack.push(node.left)
        }
    }
    return result
};

后序遍历


/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
    let stack = []
    let result = []
    if(root) {
        stack.push(root)
    }
    while(stack.length) {
        let node = stack.pop()
        if(!node) {
            result.push(stack.pop().val)
            continue
        }
        stack.push(node)
        stack.push(null)
        if(node.right) {
            stack.push(node.right)
        }
        if(node.left) {
             stack.push(node.left)
        }
    }
    return result
};