二叉查找树概念与相关leetcode题目

概念

二叉查找树,也叫二叉搜索树。树中任意一个节点,该节点的左子树中每个节点的值,都小于该节点的值;右子树中每个节点的值,都大于该节点的值。

查找

从根节点开始查找,若查找的数据等于根节点的值,则返回;若查找的数据小于根节点的值,则在左子树递归查找;若查找的数据大于根节点的值,则在右子树递归查找。

插入

插入的数据一般会放置到叶子节点上,因此也是从根节点开始遍历。

  • 如果插入的数据比节点的数据大,且节点的右子树为空,那么直接将插入数据作为右子树节点;如果不为空,则循环遍历右子树,查找插入位置。

  • 同理,如果插入的数据比节点数据小,且节点的左子树为空,那么将插入数据作为左子树节点;如果不为空,则循环遍历左子树,查找插入位置。

删除

删除二叉查找树的操作分为三种情况:

一、删除的节点没有左右子树,那么直接将父节点指向该删除节点的指针,设置为null

二、删除的节点有一个子节点,那么将父节点的指向删除节点的指针,改为指向删除节点的子节点

三、删除的节点有两个子节点,需要遍历找到删除节点的右子树中最小的节点,将最小的节点替换到删除节点上,最后将最小节点删除

时间复杂度

时间复杂度和树的高度成正比,即o(height)

一、最坏情况

若子节点都在某一侧,就会退化成链表,时间复杂度为o(n)

二、最稳定情况

对于n个节点的完全二叉树来说,树的高度介于这两者之间:

n >= 1+2+4+8+…+2^(L-2)+1

n <= 1+2+4+8+…+2(L-2)+2(L-1)

L 的范围是[log2(n+1), log2n +1]。完全二叉树的层数小于等于 log(2底数) n +1,也就是说,完全二叉树的高度小于等于 log(2底数) n。

显然,极度不平衡的二叉查找树,它的查找性能肯定不能满足我们的需求。我们需要构建一种不管怎么删除、插入数据,在任何时候,都能保持任意节点左右子树都比较平衡的二叉查找树,因此衍生出一种特殊的二叉查找树,平衡二叉查找树。平衡二叉查找树的高度接近 logn,所以插入、删除、查找操作的时间复杂度也比较稳定,是 O(logn)。

实战题

leetcode 104题,如何求一颗二叉树的高度


public int maxDepth(TreeNode root) {

if (root == null) return 0;

if (root.left == null && root.right == null) return 1;

int leftDepth = maxDepth(root.left);

int rightDepth = maxDepth(root.right);

return leftDepth >= rightDepth ? leftDepth + 1 : rightDepth + 1;

}

leetcode 450题,二叉查找树的删除操作


public TreeNode deleteNode(TreeNode root, int key) {

TreeNode del = root;

TreeNode delParent = null;

// 查找删除节点

while (del != null) {

if (del.val == key) break;

if (key > del.val) {

delParent = del;

del = del.right;

} else {

delParent = del;

del = del.left;

}

}

if (del == null) return root;

// 若删除节点的存在两个子节点,找到右子树的最小节点替换

if (del.left != null && del.right != null) {

TreeNode minDel = del.right;

TreeNode minDelParent = del;

while (minDel.left != null) {

minDelParent = minDel;

minDel = minDel.left;

}

del.val = minDel.val;

del = minDel;

delParent = minDelParent;

}

// 若删除节点只存在一个子节点,或删除节点没有子节点

TreeNode child;

if (del.left != null) child = del.left;

else if (del.right != null) child = del.right;

else child = null;

// 删除节点

if (delParent == null) return child;

else if (delParent.left == del) delParent.left = child;

else delParent.right = child;

return root;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值