二叉排序树增加和删除__学习笔记

概念:二叉排序树的每一个节点的左子节点都要比这个节点的值小。右子节点都要比这个节点的值大
增加节点:首先判断大小,小的话如果当前节点左子节点为空则直接插入否则向左递归,大的话如果当前节点右子节点为空直接插入否则向右递归;(一般不能出现相等的情况,出现的话左右都可)
删除:删除情况有三种:
1、删除的是叶子节点
2、删除的是只有一个子树的非叶子节点
3、删除的是左右子树都有的非叶子节点
PS:为了满足删除需要,需要一个查找要删除节点的函数和一个查找要删除节点的父节点的函数,以下用node表示要删除节点,parent表示要删除节点的父节点
对于第一种情况:直接让parent的left或right 指向null,但可能会出现当前节点parent为空也就是只有一个根节点的时候,这是后需要判断一下
对于第二种情况:直接让parent对应的left或right 指向node对应的left或rright就好了,但是可能会出现parent为空的情况,也就是node是根节点而且只有一个子树的情况,这种情况只需要root指向node对应的left或right就好了
对于第三种情况:为了维持二叉排序树的特征应该找到node右子树中最小的来接替node的位置,或者找到node左子树中最大的来接替node的位置,根据二叉排序树的特点,右子树中最小的就是右子树中最左节点,左子树中最大的就是左子树汇总最右节点,找到这个节点后也有两种思路1、将这个节点删掉,然后让node的值等于找到的这个节点的值,2、将这个节点删掉,让parent指向这个节点,这个节点的left和right指向node的left和right,不过这时又会遇到之前的问题,如果parent为空的话,应该让root指向这个节点。
附上代码:不过代码有点啰嗦,不过也是因为情况比较多,不过希望有更简洁的代码,欢迎指正交流。

package cn.study.TestDemo.DataStructure.Tree.binarySortTree;

public class binarySortTreeDemo {
    Node root;

    //删除
    Node removeNode(int id) {
        Node node = searchNode(id);
        Node parent = searchParent(id);
        //若果没找到直接返回
        if (node == null) {
            return null;
        }
        //要删除的节点就是根节点
        //如果要删除的节点是叶子节点
        if (node.left == null && node.right == null) {
            if (parent == null) {
                root = null;
                return node;
            } else {
                if (parent.left != null && parent.left == node) {
                    parent.left = null;
                }
                if (parent.right != null && parent.right == node) {
                    parent.right = null;
                }
            }
        }
        //如果要删除的节点左右子树都有
        //1、此时可以从右子树中找到最小的,将其删掉,然后让parent指向这个最小的,这个最小的的left和right再指向原本要删节点的left和right
        //2、或者直接不用这么麻烦,找到最小的之后,只要将要删除的节点的值替换为这个最小的值就好了,不过有个弊端,那就是无法返回原本要删除的那个节点了,因为值改变了,除飞用个变量把原本的值记录下来
        else if (node.left != null && node.right != null) {
            Node temp = node.right;
            while (temp.left != null) {
                temp = temp.left;
            }
            Node rightMinNode = removeNode(temp.id);
            node.id = rightMinNode.id;
           /* if (parent.left != null && parent.left == node) {
                parent.left = temp;
                temp.left = node.left;
                temp.right = node.right;
            }
            if (parent.right != null && parent.right == node) {
                parent.right = temp;
                temp.left = node.left;
                temp.right = node.right;
            }*/
        }
        //如果要删除的节点只有一个子树
        else {
            //如果要删除节点只有右子树
            if (node.right != null) {
                if (parent == null) {
                    root = root.right;
                } else {
                    if (parent.left != null && parent.left == node) {
                        parent.left = node.right;
                    }
                    if (parent.right != null && parent.right == node) {
                        parent.right = node.right;
                    }
                }
            }
            //如果要删除的节点只有左子树
            if (node.left != null) {
                if (parent == null) {
                    root = root.left;
                } else {
                    if (parent.left != null && parent.left == node) {
                        parent.left = node.left;
                    }
                    if (parent.right != null && parent.right == node) {
                        parent.right = node.left;
                    }
                }
            }
        }
        return node;
    }

    //中序遍历
    static void infixTraverse(Node node) {
        if (node == null) {
            return;
        }
        if (node.left != null) {
            infixTraverse(node.left);
        }
        System.out.print(node.id + "...");
        if (node.right != null) {
            infixTraverse(node.right);
        }
    }

    void setRoot(Node root) {
        this.root = root;
    }

    void addNode(Node node) {
        if (root == null) {
            root = node;
        } else {
            root.addNode(node);
        }
    }

    Node searchNode(int id) {
        if (root == null) {
            return null;
        }
        return root.searchNode(id);
    }

    Node searchParent(int id) {
        if (root == null) {
            return null;
        }
        return root.searchParent(id);
    }

    static class Node {
        int id;
        String value;
        Node left;
        Node right;

        Node(int id) {
            this.id = id;
        }

        // 增加节点
        void addNode(Node node) {
            if (this.id > node.id) {
                if (this.left == null) {
                    this.left = node;
                } else {
                    this.left.addNode(node);
                }
            } else {
                if (this.right == null) {
                    this.right = node;
                } else {
                    this.right.addNode(node);
                }
            }
        }

        //查找要删除的节点
        Node searchNode(int id) {
            if (this.id == id) {
                return this;
            }
            if (this.id < id) {
                if (this.right != null) {
                    return this.right.searchNode(id);
                }
            } else {
                if (this.left != null) {
                    return this.left.searchNode(id);
                }
            }
            return null;
        }

        //查找要删除的节点的父节点
        Node searchParent(int id) {
            if ((this.left != null && this.left.id == id) || (this.right != null && this.right.id == id)) {
                return this;
            }
            if (this.id < id) {
                if (this.right != null) {
                    return this.right.searchParent(id);
                }
            } else {
                if (this.left != null) {
                    return this.left.searchParent(id);
                }
            }
            return null;
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值