当前位置:网站首页>删除二叉搜索树中的节点附图详解
删除二叉搜索树中的节点附图详解
2022-07-04 16:24:00 【风能保暖内裤】
文章目录
二叉搜索树的删除较为繁琐,但是静下心来相信很快就能吸收!主要分为两步:首先是查找待删除节点,然后针对这个节点进行删除。
我们用cur变量搜索,用parent变量表示curr的双亲结点
搜索待删除节点
搜索不是这篇文章的重点,我们直接上代码
public boolean delete(int key) {
// wirte code here,主要分为三种情况
Node parent = null;
Node cur = root;//cur负责找到需要删除的节点
while (cur != null) {
if (cur.key < key) {
parent = cur;
cur = cur.right;
} else if (cur.key > key) {
parent = cur;
cur = cur.left;
} else {
//△到这里,我们就找到了待删除节点,即cur
deleteNode(parent, cur);
//deleteNode方法就是删除cur节点
return true;
}
}
return false;
}
注意:到上面代码的三角形处,我们就找到了待删除节点cur
正文(删除cur节点)
我们分为三种情况:(cur节点就是待删除节点,parent是cur的双亲结点,下文不赘述)
- cur.left = null;
- cur.right = null;
- cur.left != null && cur.right != null;
情况1:cur.left = null
这次情况又分为3种情况
- cur 是 根节点
- cur 是 parent 的左孩子
- cur 是 parent 的右孩子
① cur 为根节点
这种情况下,我们直接让root = root.right即可

② cur 为 parent 的左孩子
如图,我们让parent.left = cur.right即可

③ cur 为 parent 的右孩子
如图,我们让parent.right = cur.right即可
情况2:cur.right = null
- 情况 2 和情况 1 思路基本上是一样的,我们再重复一次巩固一下
- cur 是 根节点
- cur 是 parent 的左孩子
- cur 是 parent 的右孩子
① cur 为根节点
同理,只需root = root.left即可

② cur 为 parent 的左孩子
如图,我们让parent.left = cur.left
③ cur 为 parent 的右孩子
如图,我们让parent.right = cur.left
情况3:cur.left != null && cur.right != null
核心思想:在 cur 的右子树中找到值最小的节点,然后将该节点值赋给 cur ,再将该最小节点删除
- 所以就一共有两个步骤:① 找 cur 右子树最小节点,并将该最小值赋给cur ② 删除这个最小节点
步骤①
先定义 target = cur.right,再让 targetParent 为 target 的双亲结点
最终:让 target 指向 cur 右子树的最小节点,让 targetParent 指向 target的双亲
以下 ↓ 代码是让 target 指向 cur 右子树的最小节点
Node target = cur.right;//找到cur右子树中的最小节点,替换cur节点,并且删除这个最小节点
Node targetParent = cur; //target节点的双亲结点
while (target.left != null) {
//找到右子树的最小节点
targetParent = target;
target = target.left;
}
然后再赋值:cur.key = target.key;,如图
步骤②
到了这一步,我们的任务就只剩删除 target 节点了,这时再分为两种情况,也比较好理解了
- target == targetParent.left
- tartget == targetParent.right
情况1 :仅需targetParent.left = target.right
情况2:仅需targetParent.right = target.right
完成!
删除 cur 节点代码
private void deleteNode(Node parent, Node cur) {
//至此,cur指向待删除的节点
if (cur.left == null) {
//情况1,如果左孩子为空
if (cur == root) {
root = cur.right;
} else if (parent.left == cur) {
parent.left = cur.right;
} else {
parent.right = cur.right;
}
} else if (cur.right == null) {
//情况2,如果右孩子为空
if (cur == root) {
root = cur.left;
} else if (parent.left == cur) {
parent.left = cur.left;
} else {
parent.right = cur.left;
}
} else {
//情况3,如果左右孩子都不为空
Node target = cur.right;//找到cur右子树中的最小节点,替换cur节点值,并且删除这个最小节点
Node targetParent = cur; //target节点的双亲结点
while (target.left != null) {
//找到右子树的最小节点
targetParent = target;
target = target.left;
}
cur.key = target.key; //覆盖cur值
if (target == targetParent.left) {
targetParent.left = target.right;
} else {
targetParent.right = target.right;
}
}
}
全代码
public boolean delete(int key) {
// wirte code here,主要分为三种情况
Node parent = null;
Node cur = root;//cur负责找到需要删除的节点
while (cur != null) {
if (cur.key < key) {
parent = cur;
cur = cur.right;
} else if (cur.key > key) {
parent = cur;
cur = cur.left;
} else {
deleteNode(parent, cur);
return true;
}
}
return false;
}
private void deleteNode(Node parent, Node cur) {
//至此,cur指向待删除的节点
if (cur.left == null) {
//如果左孩子为空
if (cur == root) {
root = cur.right;
} else if (parent.left == cur) {
parent.left = cur.right;
} else {
parent.right = cur.right;
}
} else if (cur.right == null) {
//如果右孩子为空
if (cur == root) {
root = cur.left;
} else if (parent.left == cur) {
parent.left = cur.left;
} else {
parent.right = cur.left;
}
} else {
//如果左右孩子都不为空
Node target = cur.right;//找到cur右子树中的最小节点,替换cur节点,并且删除这个最小节点
Node targetParent = cur; //target节点的双亲结点
while (target.left != null) {
//找到右子树的最小节点
targetParent = target;
target = target.left;
}
cur.key = target.key; //覆盖
if (target == targetParent.left) {
targetParent.left = target.right;
} else {
targetParent.right = target.right;
}
}
}
边栏推荐
- Is BigDecimal safe to calculate the amount? Look at these five pits~~
- The top half and bottom half of the interrupt are introduced and the implementation method (tasklet and work queue)
- Once the "king of color TV", he sold pork before delisting
- Make a grenade with 3DMAX
- Why are some online concerts always weird?
- [proteus simulation] printf debugging output example based on VSM serial port
- 通过事件绑定实现动画效果
- [cloud native] what is the "grid" of service grid?
- Lua EmmyLua 注解详解
- 国产数据库TiDB初体验:简单易用,快速上手
猜你喜欢

谷粒商城(一)

MySQL常用增删改查操作(CRUD)

Ks007 realizes personal blog system based on JSP

估值900亿,超级芯片IPO来了

mysql5.7安装教程图文详解

CocosCreator事件派發使用

Detectron2 installation method

Weima, which is going to be listed, still can't give Baidu confidence

Superscalar processor design yaoyongbin Chapter 6 instruction decoding excerpt

如何提高开发质量
随机推荐
【211】go 处理excel的库的详细文档
With the stock price plummeting and the market value shrinking, Naixue launched a virtual stock, which was deeply in dispute
Flask lightweight web framework
同事悄悄告诉我,飞书通知还能这样玩
New technology releases a small program UNIPRO to meet customers' mobile office scenarios
超标量处理器设计 姚永斌 第5章 指令集体系 摘录
shell脚本的替换功能实现
【210】PHP 定界符的用法
Oppo Xiaobu launched Obert, a large pre training model, and promoted to the top of kgclue
正则表达式
General environmental instructions for the project
[daily question] 556 Next bigger element III
Cocoscreator event dispatch use
你应该懂些CI/CD
mysql5.7安装教程图文详解
五千字讲清楚团队自组织建设 | Liga 妙谈
Self reflection of a small VC after two years of entrepreneurship
股价大跌、市值缩水,奈雪推出虚拟股票,深陷擦边球争议
The top half and bottom half of the interrupt are introduced and the implementation method (tasklet and work queue)
爬虫初级学习