二叉搜索树

3/1/2022 BST

# 二叉搜索树BST

# 定义特性

二叉搜索树(BST)是一种特殊的二叉树,它满足如下特性:

  • 左子树的节点 均小于 根节点的值,右子树的节点 均大于 根节点的值
  • BST的中序遍历结果是递增的有序数列

BST具有以下优点:

  • BST查找、删除、增加的时间复杂度由于二分的存在,时间复杂度均为O(h),在高度平衡的BST下时间复杂度均为O(lgn),对于需要查找和删除或插入同时进行的操作,用BST更为合适

# 基本操作

BST的基本操作有三种:查找、插入、删除,其中较为复杂的为删除操作。

  1. 查找,根据BST的特性,可二分快速确定去左右子树查找
  2. 插入,方式有很多,一般用是整体操作变化最小的经典方式,即根据BST的特性,在合适的节点上插入新节点。
  3. 删除,删除的情况较为复杂,需要根据删除的节点分为三种情况:
    • 为叶子节点时,直接删除
    • 如果右子树存在,则寻找右子树中最小的节点(即删除节点的后继节点)替代该节点,然后再递归删除该节点
    • 如果左子树存在,则寻找左子树中最大的节点(即删除节点的前驱节点)替代该节点,然后再递归删除该节点

# 代码示例

这里列出三种基本操作的JS代码供参考,这里优先使用递归法,因为递归法更容易理解,但是从代码性能上,迭代法性能会更优。

详细的迭代、递归解法,参考:

  • 700.二叉搜索树中的搜索
  • 701.二叉搜索树中的插入操作
  • 450.删除二叉搜索树中的节点

# 查找

var searchBST = function (root, val) {
  while (root) {
    if (root.val == val) return root;
    root = val < root.val ? root.left : root.right;
  }
  return null;Ï
};

# 插入

var insertIntoBST = function (root, val) {
  if (!root) {
    return new TreeNode(val);
  }

  if (val < root.val) {
    root.left = insertIntoBST(root.left, val);
  } else if (val > root.val) {
    root.right = insertIntoBST(root.right, val);
  } else {
    return null;
  }
  return root;
};

# 删除

var deleteNode = function (root, key) {
  if (!root) return null;

  // 寻找node在中序遍历的前驱节点,即左子树中最大的值
  const predecessor = (node) => {
    node = node.left;
    while (node && node.right) {
      node = node.right;
    }
    return node.val;
  };

  // 寻找node在中序遍历的后继节点,即右子树中最小的值
  const successor = (node) => {
    node = node.right;
    while (node && node.left) {
      node = node.left;
    }
    return node.val;
  };

  if (key < root.val) {
    // 左子树中寻找需要删除的节点
    root.left = deleteNode(root.left, key);
  } else if (key > root.val) {
    // 右子树中寻找需要删除的节点
    root.right = deleteNode(root.right, key);
  } else {
    if (!root.left && !root.right) {
      // 叶子节点直接删除
      // 分为两种情况,只有根节点 和 普通的叶子节点,但处理都是一样。如果是根节点返回null,如果是叶子节点,则由于递归,父节点会置位null
      root = null;
    } else if (root.right) {
      // 如果右子树存在,则寻找右子树中最小的节点替代该节点,然后再递归删除该节点
      root.val = successor(root);
      root.right = deleteNode(root.right, root.val);
    } else {
      // 如果右子树不存在,则寻找左子树中最大的节点替代该节点,然后再递归删除该节点
      root.val = predecessor(root);
      root.left = deleteNode(root.left, root.val);
    }
  }
  return root;
};

# 案例分析

这里重点讨论下220.存在重复元素-iii,这一题通过BST解法,能够综合的运用BST,且加深对BST这种数据结构的认识。

需要注意以下两点:

1. 220这一题的最优解法为桶排序,但是这里为了练习BST,重点从BST的角度去梳理。
1. 220这一题BST解法优先使用平衡二叉树,即使用红黑或者AVL树,优先使用红黑,这样能保证树操作的时间复杂度在O(lgn),但是这里为了练习BST,所以不做延伸,仅用简单的BST来实现。

# 附录

# 树结构中的常见用语

  • 节点的深度 - 从树的根节点到该节点的边数
  • 节点的高度 - 该节点和叶子之间最长路径上的边数
  • 树的高度 - 其根节点的高度

即,深度为从上往下,高度为从下往上。

# 平衡二叉搜索树

平衡二叉搜索树,是高度平衡的二叉搜索树,指每个节点的两个子树高度相差不会超过1。

当插入和删除时,平衡二叉搜索树,会自动调整高度,自动保持高度最小。

常用的平衡二叉搜索树:

Last Updated: 6/23/2022, 5:33:14 PM