数据结构-二叉排序树(Java实现)

一、创建二叉排序树 添加二叉树结点以及遍历
二、删除一颗二叉排序数的结点
这里分为三种情况:
1.删除的结点为叶子结点
    ①首先要去找需要删除的结点 targetNode
    ②找到需要删除的结点的父结点 parentNode 判断需要删除的结点 targetNode是左子结点还是右子结点
    ③根据②判断 parentNode.left = null;
               parentNode.right = null;
2.删除的结点有一个子结点
    ①首先要去找需要删除的结点 targetNode
    ②找到需要删除的结点的父结点 parentNode 判断需要删除的结点 targetNode是左子结点还是右子结点
    ③如果需要删除的是结点有左子节点
            如果targetNode为父结点的左节点parentNode.left = targetNode.left
            如果targetNode为父结点的右节点parentNode.right = targetNode.left

      如果需要删除的是结点有右子节点
            如果targetNode为父结点的左节点parentNode.left = targetNode.right
            如果targetNode为父结点的右节点parentNode.right = targetNode.right
3.删除的结点有两个子节点
    ①首先要去找需要删除的结点 targetNode
    ②找到需要删除的结点的父结点 parentNode 判断需要删除的结点 targetNode是左子结点还是右子结点
    ③找到删除结点的右节点下的所有子树的最小值 先创建一个临时变量保存下来 将其删除
    ④最后将targetNode指向临时变量
package datastructure.tree.binarysorttree;

/*
    @CreateTime 2021/9/18 15:06
    @CreateBy cfk

*/

public class BinarySortTree {

    public static void main(String[] args) {
        /*
                  7
              3       10
           1    5   9   12
             2
         */
        int[] arr = {7,3,10,12,5,1,9,2};

        //创建一颗二叉排序树
        BinarySort binarySort = new BinarySort();

        //对二叉排序树进行循环添加
        for (int i = 0; i < arr.length; i++) {
            binarySort.add(new Node(arr[i]));
        }

        binarySort.inOrder();

        binarySort.deleteNode(1);
        binarySort.deleteNode(2);
        binarySort.deleteNode(5);
        binarySort.deleteNode(3);
        binarySort.deleteNode(9);
        binarySort.deleteNode(10);
        binarySort.deleteNode(12);
        binarySort.deleteNode(7);
        System.out.println("===============");
        binarySort.inOrder();
    }
}

//创建二叉排序树
class BinarySort{
    public Node root;

    //返回以node为根节点的二叉树最小值
    public int delRightTreeMin(Node node) {
        Node target = node;

        //循环查找左子节点 就会找到最小值
        while (target.left != null) {
            target = target.left;
        }

        deleteNode(target.id);
        return target.id;
    }

    //删除叶子节点
    public void deleteNode(int id) {
        if (root == null) {
            return;
        }else {
            //找到需要删除的节点
            Node targetNode = root.searchNode(id);

            if (targetNode == null ) {
                return;
            }

            //如果这颗二叉树只有一个节点
            if (root.left == null && root.right == null) {
                root = null;
                return;
            }

            //找到父结点
            Node parent = searchParent(id);

            //如果要删除的是叶子节点
            if (targetNode.left == null && targetNode.right == null) {
                if (parent.left != null && parent.left.id == id) {
                    parent.left = null; // 删除左子节点
                } else if (parent.right != null && parent.right.id == id) {
                    parent.right = null; // 删除右节点
                }
                //如果目标节点的左右节点都不为空的话
            }else if (targetNode.left != null && targetNode.right !=null){
                targetNode.id = delRightTreeMin(targetNode.right);

            }else {
                //删除只有一个子树的节点
                if (targetNode.left != null) {
                    //这里的判断节点是否还有父结点 如果没有父结点说明此处只有两个节点
                    //如果不做此判断 删除时根节点没有父结点会造成空指针异常
                    if (parent != null) {
                        //如果targetNode是parent的左子节点
                        if (parent.left != null && parent.left.id == id) {
                            parent.left = targetNode.left;
                        }else {
                            parent.right = targetNode.left;
                        }
                    }else {
                        root = targetNode.left;
                    }
                }else {
                    if (parent != null) {
                        if (parent.left != null && parent.left.id == id) {
                            parent.left = targetNode.right;
                        }else {
                            parent.right = targetNode.right;
                        }
                    }else {
                        root = targetNode.right;
                    }
                }

            }



        }
    }

    //查找要删除的节点
    public Node search(int id) {
        if (root == null) {
            return null;
        }else {
            return root.searchNode(id);
        }

    }

    //查找要删除节点的父结点
    public Node searchParent(int id) {
        if (root == null) {
            return null;
        }else {
            return root.searchParentNode(id);
        }
    }

    //添加节点
    public void add(Node node){
        if (root == null) {
            root = node;
        }else {
            root.add(node);
        }
    }

    //中序遍历
    public void inOrder() {
        if (root == null) {
            System.out.println("节点为空");
        }else {
            root.inOrder();
        }
    }

}



//创建节点
class Node {
    public int id;

    public Node left;
    public Node right;

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

    @Override
    public String toString() {
        return "Node{" +
                "id=" + id +
                '}';
    }


    //添加节点的方法
    public void add(Node node) {

        if (node == null) {
            return;
        }

        if (node.id < this.id) {
            //如果左节点为空
            if (left == null) {
                this.left = node;
            }else {
                //否则递归判断 把节点添加到左子节点的子节点 以此类推
                this.left.add(node);
            }

        }else {
            //如果右节点为空
            if (right == null) {
                this.right = node;
            }else {
                //同左节点
                this.right.add(node);
            }
        }


    }

    //中序遍历
    public void inOrder() {
        if (this.left != null) {
            this.left.inOrder();
        }

        System.out.println("node=>"+this.id);

        if (this.right != null) {
            this.right.inOrder();
        }
    }

    //通过id查找对应的结点
    public Node searchNode(int id) {
        //如果当前结点就是要找的结点就直接输出
        if (id == this.id) {
            return this;
        } else if (id < this.id) { //如果要找的结点小于此结点并且左结点不为空 则递归左边全部
            if (this.left == null) {
                return null;
            }
            return this.left.searchNode(id);
        } else { //如果要找的结点小于此结点并且右结点不为空 则递归右边全部
            if (this.right == null) {
                return null;
            }
            return this.right.searchNode(id);
        }
    }

    //根据子节点id查找对应结点的父结点
    public Node searchParentNode(int id) {

        //如果当前结点的左子或右子节点id等于传入id则返回当前节点
        if (this.left != null && this.left.id == id ||
            this.right != null && this.right.id == id){
            return this;
        }else {
            //如果查找的值小于当前结点的值,并且当前结点的左子结点不为空
            if (this.id > id && this.left != null) {
                return this.left.searchParentNode(id);
                //如果查找的值大于当前结点的值,并且当前结点的右子结点不为空
            } else if (this.id < id && this.right != null) {
                return this.right.searchParentNode(id);
            } else {
                return null;//没有找到父结点
            }
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值