zoukankan      html  css  js  c++  java
  • java

    二叉排序树(BST)

    任何一个节点, 左边的节点值都比他小,右边的都比他大,中序遍历得到的是从小到大的数列。

    可以用来排序和快速查找。

    1. 添加

    从根节点向下寻找,比当前节点小就向左,比当前节点大就向右,直到最低端,然后称为新的叶子节点(没有孩子节点的节点)。

    2. 查询

    从根节点向下寻找,比当前节点小就向左,比当前节点大就向右,相等时就找到了

    3. 删除(主要难点)

    3种情况

    1. 没有孩子节点

    叶子节点可以直接删掉,用null代替其原来位置

    2. 有一个孩子

    用孩子节点代替自己。

    3. 有两个孩子

    用右孩子的最小叶子节点,或者左孩子的最大叶子节点代替自己,然后删掉那个叶子节点

    本质就是找个跟自己中序遍历时挨着的节点代替自己,这样不会影响整体结构。

    平衡二叉树(以后再整理=。=)的继承节点是找自己右孩子的左叶子节点,所以这里就用右孩子的左叶子节点代替了。

    package tree;
    
    public class BinarySortTree {
    
        Node root;
    
        public BinarySortTree(){
            root = null;
        }
    
        //添加节点
        public void add(int num){
            if(root == null) {
                root = new Node(num);
            }
            else{
                Node n = new Node(num);
                root.add(n);
            }
        }
    
        //中序遍历 (按顺序从小到大)
        public void show(){
            if(root == null){
                System.out.println("树为空");
            }
            else{
                root.show();
            }
        }
    
        //发现节点
        public Node findNode(int num){
            if(root == null){
                System.out.println("树为空");
                return null;
            }
            else{
                return root.findNode(num);
            }
        }
    
        //发现父节点
        public Node findParentNode(int num){
            if(root == null){
                System.out.println("树为空");
                return null;
            }
            else{
                return root.findParentNode(num);
            }
        }
    
        //发现以某个节点为根节点的子树的最小叶子节点(用来找继承者)
        public Node findSubTreeMin(Node node){
            //因为只是为了找最小,每个节点左边的都比他小,所以只遍历左边
            //不过如果有重复值,按照插入的规则会在左边,会继续向左找,保证找到的是叶子节点。
            if(node.left == null){
                return node;
            }
            else{  //左子树存在,说明有更小的值,继续向左找
                return findSubTreeMin(node.left);
            }
        }
    
        //删除节点
        public void delete(int num){
            if(root == null){
                System.out.println("树为空");
                return;
            }
            else{
                Node targetNode =  findNode(num);
                if (targetNode == null) {
                    System.out.println("没有发现目标节点");
                    return;
                }
                Node parentNode = findParentNode(num);
                if (parentNode == null) {   //没有父亲节点,说明是root
                    System.out.println("目标节点是root");
                    if(root.left != null && root.right == null){ //左节点不为空, 右节点为空
                        root = root.left;
                        return;
                    }
                    else if(root.left == null && root.right != null){ //左节点不为空, 右节点为空
                        root = root.right;
                        return;
                    }
                    else if(root.left == null && root.right == null){ //左右都为空
                        root = null;
                        return;
                    }
                    //3.两个孩子, 用左边最大的叶子节点或者右边最小的叶子节点代替自己 (这里写的是用右边最小的代替)
                    //**********注意,如果这里是用右边最小代替,插入的时候重复值要插在左边,不然会导致找到的不是叶子节点,出现问题。
                    //上面写的方法是发现子树的最小节点,这里是发现目标右边子树最小的节点,所以参数是root.right
                    if(root.left != null && root.right != null){
                        Node rightMinNode = findSubTreeMin(targetNode.right);
                        int temp = rightMinNode.value;
                        delete(temp);
                        root.value = temp;
    
                    }
                }
    
                else{ // target不是根节点
                    // 1. 叶子节点, 2.一个孩子, 3,两个孩子
                    //1. 叶子节点, 用null代替自己
                    if(targetNode.left == null && targetNode.right == null){ //左右都为空 (叶子节点)
                        //判断是父节点的左孩子还是右孩子,然后置空;
                        if(parentNode.left != null && parentNode.left == targetNode){
                            parentNode.left = null;
                            return;
                        }
                        else if(parentNode.right != null && parentNode.right == targetNode){
                            parentNode.right = null;
                            return;
                        }
                    }
                    //2.一个孩子, 用孩子代替自己
                    if(targetNode.left != null && targetNode.right == null){ //有左孩子没有右孩子,把左孩子放在自己当前位置
                        //判断是父节点的左孩子还是右孩子,然后放置
                        if(parentNode.left != null && parentNode.left == targetNode){
                            parentNode.left = targetNode.left;
                            return;
                        }
                        else if(parentNode.right != null && parentNode.right == targetNode){
                            parentNode.right = targetNode.left;
                            return;
                        }
                    }
                    if(targetNode.left == null && targetNode.right != null){ //有右孩子没有左孩子,把右孩子放在自己当前位置
                        //判断是父节点的左孩子还是右孩子,然后放置
                        if(parentNode.left != null && parentNode.left == targetNode){
                            parentNode.left = targetNode.right;
                            return;
                        }
                        else if(parentNode.right != null && parentNode.right == targetNode){
                            parentNode.right = targetNode.right;
                            return;
                        }
                    }
                    //3.两个孩子, 用左边最大的叶子节点或者右边最小的叶子节点代替自己 (这里写的是用右边最小的代替)
                    //上面写的方法是发现子树的最小节点,这里是发现目标右边子树最小的节点,所以参数是targetNode.right
                    if(targetNode.left != null && targetNode.right != null){
                        Node rightMinNode = findSubTreeMin(targetNode.right);
                        //判断是父节点的左孩子还是右孩子,然后放置
                        if(parentNode.left != null && parentNode.left == targetNode){
                            int temp = rightMinNode.value;
                            delete(temp);
                            parentNode.left.value = temp;
                            return;
                        }
                        else if(parentNode.right != null && parentNode.right == targetNode){
                            int temp = rightMinNode.value;
                            delete(temp);
                            parentNode.right.value = temp;
                            return;
                        }
                    }
                }
            }
        }
    
    
        public static void main(String[] args){
            BinarySortTree bst = new BinarySortTree();
            bst.add(5);
            bst.add(4);
            bst.add(6);
            bst.add(2);
            bst.add(8);
            bst.add(3);
            bst.add(9);
            bst.add(1);
            bst.add(7);
    
            bst.add(5);
            bst.add(4);
            bst.add(6);
    
    
    
    
            System.out.println("中序遍历");
            bst.show();
            System.out.println();
    
            bst.delete(5);  //删除一个节点
            bst.show();
    
    
    
        }
    
        public class Node{
            public int value;
            public Node left;
            public Node right;
    
            public Node(int value){
                this.value = value;
            }
    
            public void add(Node n){
                if(n == null){
                    return;
                }
                else{
                    if(n.value <= this.value){  //相等的放在左边
                        if(this.left == null){
                            this.left = n;
                        }
                        else{
                            this.left.add(n);
                        }
                    }
                    else{  // >=
                        if(this.right == null){
                            this.right = n;
                        }
                        else{
                            this.right.add(n);
                        }
                    }
                }
            }//add end
    
            public void show(){
                if(this.left != null){
                    this.left.show();
                }
                System.out.print(this.value + " ");
    
                if(this.right != null){
                    this.right.show();
                }
            }
    
            public void delete(int num){
                Node father = this;
                Node child = null;
            }
    
            public Node findNode(int num){
                Node n = null;
    
                if(this.value == num){
                    return this;
                }
    
                else if(num < this.value && this.left != null){
                    return this.left.findNode(num);
                }
    
                else if(num >= this.value && this.right != null){
                    return this.right.findNode(num);
                }
                else{
                    return null;
                }
            }
    
            public Node findParentNode(int num){
                Node n = null;
    
                if(this.left != null && this.left.value == num){ //num 是左孩子
                    return this;
                }
    
                else if(this.right != null && this.right.value == num){ //num 是右孩子
                    return this;
                }
    
                else if(num < this.value && this.left != null){// num不是孩子节点,且比当前节点小,继续向左寻找
                        return this.left.findParentNode(num);
                }
    
                else if(num >= this.value && this.right != null){// num不是孩子节点,且比当前节点大,继续向右寻找
                        return this.right.findParentNode(num);
                }
                else{  //进行不下去了,说明无法发现节点,返回null
                    System.out.println("父节点不存在");
                    return null;
                }
            }
    
        }
    }
  • 相关阅读:
    满巢尽洒英雄泪
    谋略的原则——经商就是讲谋略的交易
    杨文军(为奥运冠军名字作诗)
    邹市明 (为奥运冠军名字作诗)
    王励勤 (为奥运冠军名字作诗)
    想成功创业:要掌握“三笔钱”和“六三一”原则
    王丽萍(再帮别人名字作诗)
    陆春龙(为奥运冠军名字作诗)
    殷剑 (为奥运冠军名字作诗)
    孟关良(为奥运冠军名字作诗)
  • 原文地址:https://www.cnblogs.com/clamp7724/p/11861860.html
Copyright © 2011-2022 走看看