博客主页:敲代码的布莱恩特
欢迎点赞 收藏 ⭐留言 欢迎讨论!
本文由 【敲代码的布莱恩特】 原创,首发于 CSDN
由于博主是在学小白一枚,难免会有错误,有任何问题欢迎评论区留言指出,感激不尽!✨
精品专栏(不定时更新)【JavaSE】 【Java数据结构】【LeetCode】
二叉搜索树又称 二叉排序树
,它或者是一棵空树,或者是具有以下性质的二叉树:
所有节点的值都小于根节点的值
所有节点的值都大于根节点的值
左右子树
也分别为二叉搜索树
注意
:二叉搜索树中没有重复的元素
二叉树是由一个一个节点组成的,先定义好
节点的属性
代码实现:
public class Node{
int key;//节点值
Node left;//左孩子节点
Node right;//右孩子节点
public Node(int key){//重写一下节点的构造方法
this.key = key;
}
}
Node root = null;//一开始根节点为空
查找过程:
不存在
。/**
* 在搜索树中查找 key,如果找到,返回 key 所在的结点,否则返回 null
* @param key
* @return
*/
public Node search(int key){
Node cur = root;//cur从root开始走
while(cur != null){
if(cur.key == key){//如果cur的值与key相等,则返回cur
return cur;
}else if(key > cur.key){//key值比cur的值大,cur往右节点走
cur = cur.right;
}else if(key < cur.key){//key值比cur的值小,cur往左节点走
cur = cur.left;
}
}
return null;//root为空,或者二叉树里没有这个节点,返回空值
}
插入过程:
代码实现:
/**
* 插入
* @param key
* @return true 表示插入成功, false 表示插入失败
*/
public Boolean insert(int key){
if(root == null){//如果根节点空,则第一个节点就是根节点
root = new Node(key);
return true;
}
Node cur = root;//用cur从root位置开始往下走
Node parent = null;//需要用一个parent节点来记录上一个节点
//通过while循环来找插入位置
while(cur != null){
if (key == cur.key){
return false;//如果二叉树里已经有这个值,就无法插入
}
else if (key < cur.key){//key比cur的值小,说明要插到左边
parent = cur;//记录上一个节点
cur = cur.left;//cur往左走
}
else if (key > cur.key){//key比cur的值大,说明要插到右边
parent = cur;//记录上一个节点
cur = cur.right;//cur往右走
}
}
//while走完了,说明是时候插入节点了,因为我们插入节点的位置一定是叶子节点的位置
//这就需要用到parent了
Node node = new Node(key);//创建要插入的新节点
if (node.key > parent.key){//比parent值大放右边
parent.right = node;
}else {
parent.left = node;//反之放左边
}
return true;//插入成功
}
设待删除结点为 cur, 待删除结点的双亲结点为 parent,删除节点的关键在于对多种情况的分析
cur.left != null && cur.right != null
待删除节点左右子树都存在
(需要使用替换法
进行删除,即在它的右子树
中寻找最小值结点
,用它的值填补到被删除节点
中,再来处理该结点的删除问题,关键就在于这个寻找最小值替代这一步
)
总而言之,这第三种情况处理方法就是,从待删除点的右树里找最小值来替换待删除点,然后将替罪羊节点的右树接到替罪羊节点的父节点后边即可,注意点就是替罪羊节点是在父节点左边还是右边
代码实现:
/**
* 删除成功返回 true,失败返回 false
* @param key
* @return
*/
public void removeKey(int key) {
if(root == null) {
return;
}
Node cur = root;
Node parent = null;
while (cur != null) {
if(cur.key == key) {
remove(parent,cur);
return;
}else if(cur.key < key){
parent = cur;
cur = cur.right;
}else {
parent = cur;
cur = cur.left;
}
}
}
private void remove(Node parent, Node cur) {
if (cur.left == null){//删除只有右孩子的节点
if (cur == root){//要删除的点是根节点
root = cur.right;
}
else if (cur == parent.left){//要删除的点在父亲节点左边
parent.left = cur.right;
}
else if (cur == parent.right){//要删除的点在父亲节点右边
parent.right = cur.right;
}
}
else if(cur.right == null){//删除只有左孩子的节点
if(cur == root) {//要删除的点是根节点
root = cur.left;
}
else if(cur == parent.left) {//要删除的点在父亲节点左边
parent.left = cur.left;
}
else if(cur == parent.right){//要删除的点在父亲节点右边
parent.right = cur.left;
}
}
else {
Node target = cur.right;
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 if(target == targetParent.right){//如果当前目标值是父节点的右孩子
targetParent.right = target.right;//就把目标节点的右孩子接到父节点的右边
}
}
}
❤原创不易,如有错误,欢迎评论区留言指出,感激不尽❤
❤ 如果觉得内容不错,给个三连不过分吧~ ❤
❤ 看到会回访~ ❤