完整代码示例-Java实现二叉排序树的查找和删除

结点类:

package DataStrcture.binarysearchtree;

public class TreeNodeDel {
    public TreeNodeDel leftNode;
    public TreeNodeDel rightNode;
    public int value;

    ///BST结点的删除
    //1. 待删除结点的查找
    public TreeNodeDel searchTargetNode(int key) {
        if (this.value == key) return this;
        //左子树递归
        if (this.value > key) {
            if (this.leftNode != null)
                return this.leftNode.searchTargetNode(key);
            //右子树递归
        } else {
            if (this.rightNode != null)
                return this.rightNode.searchTargetNode(key);
        }
        return null;
    }

    //2. 待删除结点父节点的查找
    public TreeNodeDel parentNode(int key) {
        //递归查找的结束语句(递归出口)
        if (this.leftNode != null && this.leftNode.value == key
                || this.rightNode != null && this.rightNode.value == key) {
            return this;
        } else {
            //如果查找的值小于当前结点的值,并且当前结点的左子树不为空
            if (key < this.value && this.leftNode != null) {
                return this.leftNode.parentNode(key);//往左子树递归
                // 如果查找的值大于或等于当前结点的值,并且当前结点的右子树不为空
            } else if (key >= this.value && this.rightNode != null) {
                return this.rightNode.parentNode(key); //往右子树递归
            } else {
                return null;
            }

        }

    }
    //删除结点
    /**
     * @param targetNode 待删除结点
     * @param key        结点的值
     */
    public void deleteNode(TreeNodeDel targetNode, int key) {
        TreeNodeDel parent = this.parentNode(key);
        /待删除结点可能的三种情况:
        // 1. 待删除结点为叶子结点
        //判断条件, 待删除结点的左子树或右子树为空
        if (targetNode.leftNode == null && targetNode.rightNode == null) {
            if (parent.leftNode == targetNode) {
                parent.leftNode = null;
            } else {
                parent.rightNode = null;
            }///2. 待删除结点有两棵子树
            // 判断条件, 待删除结点的左子树和右子树均不为空
        } else if (targetNode.leftNode != null && targetNode.rightNode != null) {
            //待删除结点的右子树中向左不断的遍历直到这棵右子树的最左端(这个节点为右子树的最小值)\
            TreeNodeDel minValParent = targetNode.rightNode;
            if(minValParent.leftNode == null){
                targetNode.value = minValParent.value;
                targetNode.rightNode = null;
            }else{
                //此处特别需要注意的是: 我们需要找到这个最左端结点的父节点,
                // 因为在把这个节点赋给待删除结点后, 这个节点就会被置空,
                // 用谁置空? 当然是这个节点的父节点啦
                while (minValParent.leftNode.leftNode != null) {
                    minValParent = minValParent.leftNode;
                }
                targetNode.value = minValParent.leftNode.value;
                minValParent.leftNode = null;
            }
        //3. 待删除结点只有一棵子树
        }else{
            if(parent.leftNode == targetNode){
                if(targetNode.leftNode != null){
                    parent.leftNode = targetNode.leftNode;
                }else{
                    parent.leftNode = targetNode.rightNode;
                }
            }else{
                if(targetNode.leftNode != null){
                    parent.rightNode = targetNode.leftNode;
                }
                else{
                    parent.rightNode = targetNode.rightNode;
                }
            }
        }
    }

    //构建BST
    public void addNode(TreeNodeDel node) {
        //左子树
        if (this.value > node.value) {
            if (this.leftNode == null) {
                this.leftNode = node;
            } else {
                this.leftNode.addNode(node);//往左子树递归遍历
            }

            //右子树
        } else {
            if (this.rightNode == null) {
                this.rightNode = node;
            } else {
                this.rightNode.addNode(node);
            }

        }
    }

    //中序遍历
    public void midOrder() {
        if (this.leftNode != null) this.leftNode.midOrder();

        System.out.println(this);

        if (this.rightNode != null) this.rightNode.midOrder();
    }

    //设置左右孩子结点
    public void setLeftNode(TreeNodeDel node) {
        this.leftNode = node;
    }

    public void setRightNode(TreeNodeDel node) {
        this.rightNode = node;
    }

    //构造器和toString
    public TreeNodeDel(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "TreeNodeDel{" +
                "value=" + value +
                '}';
    }
}

二叉排序树类:

package DataStrcture.binarysearchtree;

public class BSTDeleteDemo {
    private TreeNodeDel root;
    //指定根节点
    public BSTDeleteDemo(TreeNodeDel node){
        this.root = node;
    }

    public static void main(String[] args) {
        int[] arr = {7, 3, 10, 12, 5, 1, 9,13};
        BSTDeleteDemo bst = new BSTDeleteDemo(null);
        for(int x : arr){
               bst.addNode(new TreeNodeDel(x));
        }
        bst.midOrder();
        //对结点查找的测试
        int key=7;
        System.out.println("查找key为:" +key);
        bst.searchNode(key);
        System.out.println("key"+key+"的父节点为: ");
        bst.parent(key);
        System.out.println("删除key="+key+"的结点:");
        bst.deleteNode(key);
        System.out.println("删除后的二叉树为:");
        bst.midOrder();
    }
    //查找要删除的结点
    public void searchNode(int key){
        if(root == null){
            System.out.println("二叉排序树为空, 查找失败!");
        }else{
            TreeNodeDel treeNodeDel = root.searchTargetNode(key);
            System.out.println(treeNodeDel);
        }
    }
    //查找待删除结点的父节点
    public void parent(int key){
        TreeNodeDel treeNodeDel = root.parentNode(key);
        System.out.println(treeNodeDel);
    }
    ///删除结点
    public void deleteNode(int value){
        TreeNodeDel targetNode = root.searchTargetNode(value);
        if(root == null || targetNode == null){
            System.out.println(" 二叉树为空, 或者未找到待删除结点, 删除失败");
        }else{
            root.deleteNode(targetNode,value);
        }
    }
    //构建二叉树
    public void addNode(TreeNodeDel node){
        if(root == null){
            root = node;
        }else{
            root.addNode(node);

        }
    }
    //中序遍历
    public void midOrder(){
        if(root == null){
            System.out.println("二叉排序树为空, 遍历失败");
        }else{
            root.midOrder();
        }
    }
}

在这里插入图片描述

posted @ 2022-05-26 20:31  青松城  阅读(46)  评论(0编辑  收藏  举报