zoukankan      html  css  js  c++  java
  • 二叉排序树删除


    二叉排序树的删除情况比较复杂,有以下三种情况需要考虑

    • 删除叶子节点(比如:2,5,9,12)
    • 删除只有一棵子树的节点(比如1)
    • 删除有两棵子树的节点(比如:7,3,10)
    • 操作思路分析

    第一种情况:删除叶子节点

    思路:

      1. 需要先找到待删除的节点 targetNode
      1. 找到targetNode的父节点 parent
      1. 确定targetNode是parent的左节点还是右节点
      1. 根据左右来进行删除
      • 左子节点 parent.left = null
      • 右子节点 parent.right = null

    第二种情况:删除只有一棵子树的节点,比如1

    思路:

      1. 需要先找到待删除的节点targetNode
      1. 找到targetNode的父节点 parent
      1. 确定targetNode的子节点是左子节点还是又子节点
      1. targetNode是parent的左子节点还是右子节点
      1. 如果targetNode有左子节点
      • 5.1. 如果targetNode是parent的左子节点 parent.left = targetNode.left
      • 5.2. 如果targetNode是parent的右子节点 parent.right = targetNode.left
      1. 如果targetNode有右子节点
      • 6.1. 如果targetNode是parent的左子节点 parent.left = targetNode.right
      • 6.2 如果targetNode是parent的右子节点 parent.right = targetNode.right

    第三种情况:删除有两棵子树的节点(比如:7,3,10)

    思路:

      1. 需要先找到待删除的节点 targetNode
      1. 找到targetNode的父节点 parent
      1. 从targetNode的右子树中找到最小的节点
      1. 用一个临时变量,将最小的节点值保存在temp中
      1. 删除该最小的节点
      1. targetNode.val = temp
    public class BinarySortTreeDemo {
        public static void main(String[] args) {
            int[] arr = {7, 3, 10, 12, 5, 1, 9,2};
            BinarySortTree binarySortTree = new BinarySortTree();
            for (int i = 0; i < arr.length; i++) {
                binarySortTree.addNode(new Node(arr[i]));
            }
            //遍历
            binarySortTree.midOrder();
    
            //测试删除节点
            binarySortTree.delNode(5);
            binarySortTree.delNode(9);
            binarySortTree.delNode(10);
            binarySortTree.delNode(12);
            binarySortTree.delNode(7);
            binarySortTree.delNode(1);
            binarySortTree.delNode(2);
            binarySortTree.delNode(3);
    
            System.out.println("删除后");
            binarySortTree.midOrder();
        }
    }
    
    class BinarySortTree {
        private Node root;
    
        //添加节点
        public void addNode(Node node) {
            if (root == null) {
                root = node;
            } else {
                root.addNode(node);
            }
        }
    
        //中序遍历节点
        public void midOrder() {
            if (root == null) {
                System.out.println("二叉排序树为空");
            } else {
                root.midOrder();
            }
        }
    
        //查找待删除的节点
        public Node searchNode(int val) {
            if (this.root == null) {
                return null;
            } else {
                return this.root.serachNode(val);
            }
        }
    
        //查找待删除的父节点
        public Node searchParentNode(int val) {
            if (this.root == null) {
                return null;
            } else {
                return this.root.searchParentNode(val);
            }
        }
        //在待查找二叉树中找到最小的节点
        public int searchRightMin(Node node){
            while (node.left != null){
                node = node.left;
            }
            delNode(node.val);  //删除最小的节点
            return node.val;  //返回最小的节点值
        }
        //删除节点
        public void delNode(int val) {
            if (this.root == null) {
                return;
            } else {
                //先拿到待删除的节点
                Node targetNode = searchNode(val);
                if (targetNode == null) {
                    return;
                }
                //如果这棵二叉树只有一个节点
                if (this.root.left == null && this.root.right == null) {
                    if (root.val == val) {
                        root = null;
                        return;
                    }
                }
                //拿到待删除节点的父节点
                Node parent = searchParentNode(val);
                //如果删除的叶子节点
                if (targetNode.left == null && targetNode.right == null) {
                    //判断targetNode是parent的左节点还是右节点
                    if (parent.left != null && parent.left.val == val) {
                        parent.left = null;
                    } else if (parent.right != null && parent.right.val == val) {
                        parent.right = null;
                    }
                } else if (targetNode.left != null && targetNode.right != null) { // 如果删除的是带有两个叶子节点的节点
                    //从targetNode的右子树中找到最小的节点
                    int temp = searchRightMin(targetNode.right);
                    targetNode.val = temp;
                }else {  //待删除节点有一个分支
                    //如果待删除的节点有左节点
                    if (targetNode.left !=null){
                        //待删除的是根节点
                        if (parent == null){
                            this.root = targetNode.left;
                        }else {
                            //待删除的节点是左节点
                            if (parent.left!=null && parent.left.val == val){
                                parent.left = targetNode.left;
                            }else if(parent.right!=null && parent.right.val == val){ // 待删除的节点是右节点
                                parent.right = targetNode.left;
                            }
                        }
                    }else { //待删除的节点有有分支
                        if (parent == null){
                            this.root = targetNode.right;
                        }else {
                            if (parent.left!=null && parent.left.val == val){
                                parent.left = targetNode.right;
                            }else if (parent.right!=null && parent.right.val == val){
                                parent.right = targetNode.right;
                            }
                        }
                    }
                }
            }
        }
    }
    
    class Node {
    
        int val;
        Node left;
        Node right;
    
        public Node(int val) {
            this.val = val;
        }
    
        @Override
        public String toString() {
            return "Node{" +
                    "val=" + val +
                    '}';
        }
    
        //查找待删除节点的父节点
        public Node searchParentNode(int val) {
            if ((this.left != null && this.left.val == val) || (this.right != null && this.right.val == val)) {
                return this;
            } else {
                if (this.val > val && this.left != null) {
                    return this.left.searchParentNode(val);
                } else if (this.val <= val && this.right != null) {
                    return this.right.searchParentNode(val);
                } else {
                    return null;
                }
            }
        }
    
        //查找到待删除的节点
        public Node serachNode(int val) {
            if (this.val == val) {
                return this;
            } else if (this.val > val) {
                if (this.left != null) {
                    return this.left.serachNode(val);
                } else {
                    return null;
                }
            } else {
                if (this.right != null) {
                    return this.right.serachNode(val);
                } else {
                    return null;
                }
            }
        }
    
        //添加节点
        public void addNode(Node node) {
            if (this.val > node.val) {
                //需要挂载到左边
                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);
                }
            }
        }
    
        //中序遍历
        public void midOrder() {
            if (this.left != null) {
                this.left.midOrder();
            }
            System.out.println(this.val);
            if (this.right != null) {
                this.right.midOrder();
            }
        }
    }
    
    
  • 相关阅读:
    js传值到后台乱码问题
    js中string和json的相互转换
    js获取后台传给前台的值
    读取文件内容
    linux 的挂载问题
    php防止DDos攻击
    几个与特殊字符处理相干的PHP函数
    centos yum 安装nginx1.10
    linux centos6 yum php5.6
    linux mysql5.7 密码相关问题
  • 原文地址:https://www.cnblogs.com/liuzhidao/p/13887622.html
Copyright © 2011-2022 走看看