二叉树的数据删除

二叉树数据删除的四种实现

1、删除的数据没有子节点
2、删除的数据有一边有子节点
3、删除左子节点和右子节点都不为空的节点
4、根节点的删除

示例:

参考图:

在这里插入图片描述

interface Two<T> {
    public void add(Comparable<T> data);    //数据增加

    public int size();  //用于判断数据是否进行了存储

    public Object[] toArray();  //输出

    public boolean inquire(T data); //查询

    public void remove(T data); //删除数据
}

class TwoImpl<T> implements Two<T> {
    private Node root;  //根节点
    private int size;
    private int footer;
    private Object[] resultData;

    @Override
    //增加
    public void add(Comparable<T> data) {
        if (data == null) {
            return;
        }
        Node node = new Node(data);
        if (this.root == null) {    //根节点
            this.root = node;
        } else {
            this.root.addNode(this.root, node);
        }
        ++this.size;
    }

    @Override
    //获取数据的个数
    public int size() {
        return this.size;
    }

    @Override
    //数取数据输出
    public Object[] toArray() {
        if (this.size() == 0) {
            return null;
        }
        this.footer = 0;
        this.resultData = new Object[this.size];
        this.root.toArrayNode();
        return this.resultData;
    }

    @Override
    //判断数据是否存在
    public boolean inquire(T data) {
        //判断有没有数据,,没有返回false
        if (this.size() == 0) {
            return false;
        }
        //有数据进入inquireNode()内去查找数据
        return this.root.inquireNode(data);
    }

    @Override
    //输出数据
    public void remove(T data) {
        if (this.inquire(data)) { //判断数据是否存在
            if (this.root.data.compareTo(data) == 0) {
                this.root = this.delete(data);
            } else {
                this.delete(data);
            }
            --this.size;
        }
    }

    private Node delete(T data) {
        Node sonNode = null;
        Node thisNode = this.root.removeNode(data);
        /*
		1、删除的数据没有子节点
        */
        
        if (thisNode.right == null && thisNode.left == null) {
            if (thisNode.parent != null) {
                if (thisNode.parent.data.compareTo(data) <= 0) {
                    //断绝引用关系
                    thisNode.parent.right = null;
                } else {
                    //断绝引用关系
                    thisNode.parent.left = null;
                }
            }
            //判断要删除的数据在父节点的左边还是右边
            //解除节点和父节点的引用
            thisNode.parent = null;
        }

		/*
		2、删除的数据有一边有子节点
        */
        
        if ((thisNode.right != null && thisNode.left == null)
                || (thisNode.right == null && thisNode.left != null)) {
            //存储要删除的节点下面的子节点
            //删除节点在父节点的右边
                if (thisNode.right != null) {
                    //把值赋给sonNode
                    sonNode = thisNode.right;
                } else { //删除节点在父节点的左边
                    sonNode = thisNode.left;
                }
                if (thisNode.parent != null) {
                //判断要删除的数据在父节点的什么位置
                if (thisNode.parent.data.compareTo(data) <= 0) {
                    thisNode.parent.right = sonNode;
                } else {
                    thisNode.parent.left = sonNode;
                }
            }
            //修改父节点
            sonNode.parent = thisNode.parent;
        }
		/*
		3、删除左子节点和右子节点都不为空的节点
		
		4、根节点的删除
        */
        
        if (thisNode.left != null && thisNode.right != null) {
            sonNode = thisNode.right;
                while (sonNode.left != null) {
                    sonNode = sonNode.left;
                }
                 /*
                当thisNode.right == sonNode时
                sonNode.parent.left = null会使
                thisNode.left断开引用会出错
                放在sonNode.right != null判断之前先断开
                在把移动节点的右子节点放到移动节点的父节点的左边
                */
                if (thisNode.right != sonNode) {
                    //断开引用
                    sonNode.parent.left = null;
                }

                //当最左边的节点有右子节点时
                if (sonNode.right != null) {
                    //右子节点的等于移动节点的左边
                    sonNode.parent.left = sonNode.right;
                    sonNode.right.parent = sonNode.parent;
                }


                //将移动节点顶替要删除的节点
                sonNode.parent = thisNode.parent;
                if (thisNode.right != sonNode) {
                    sonNode.right = thisNode.right;
                }
                sonNode.left = thisNode.left;
                //当删除节点的父节点小于删除节点时(用于判断删除节点在父节点的什么位置)
                if (thisNode.parent != null) {
                    if (thisNode.parent.data.compareTo(data) <= 0) {
                    /*
                    移动节点等于删除节点的父节点的右子节点
                    将移动节点放到删除节点的父节点的相应方向的位置下
                     */
                        thisNode.parent.right = sonNode;
                    } else {
                    /*
                    移动节点等于删除节点的父节点的左子节点
                    将移动节点放到删除节点的父节点的相应方向的位置下
                     */
                        thisNode.parent.left = sonNode;
                    }
                }
        }
        return sonNode;
    }

    /********************内部类************************/
    private class Node {
        private Comparable<T> data; //数据
        private Node left;      //左节点
        private Node right;     //右节点
        private Node parent;    //父节点

        public Node(Comparable<T> data) {
            this.data = data;
        }

        /**
         * this.data
         *
         * @param parentNode 父节点
         * @param node       内部类实例(用于传递data数据)
         */
        public void addNode(Node parentNode, Node node) {
            if (this.data.compareTo((T) node.data) <= 0) {  //当前节点this.root小于传入节点
                if (this.right == null) {
                    this.right = node;
                    node.parent = parentNode;
                } else {
                    this.right.addNode(this.right, node);
                }
            } else {
                if (this.left == null) {
                    this.left = node;
                    node.parent = parentNode;
                } else {
                    this.left.addNode(this.left, node);
                }
            }
        }

        public void toArrayNode() { //中序解析
            if (this.left != null) {  //把左边的数据全部取出再去右边的
                this.left.toArrayNode();
            }
            TwoImpl.this.resultData[TwoImpl.this.footer++] = this.data;
            if (this.right != null) {   //左边的数据取完后才会进入右边
                this.right.toArrayNode();
            }
        }

        /**
         * 获取数据
         *
         * @param data 查询的数据
         * @return 是否存在查询的数据
         */
        public boolean inquireNode(T data) {
            //判断数据是否为根节点
            if (this.data.compareTo(data) == 0) {
                return true;
            } else {
                //当数据大于根节点时(this.data < data)
                if (this.data.compareTo(data) < 0) {
                    //判断右节点有没有值
                    if (this.right != null) {
                        //递归调用去匹配值,到最后时匹配就会在判断时不满足返回false
                        return this.right.inquireNode(data);
                    } else {
                        return false;
                    }
                } else {    //当数据小于根节点时(this.data > data)
                    //判断左节点有没有值
                    if (this.left != null) {
                        //递归调用去匹配值,到最后时匹配就会在判断时不满足返回false
                        return this.left.inquireNode(data);
                    } else {
                        return false;
                    }
                }
            }
        }

        public Node removeNode(T data) {
            //数据等于根节点
            if (this.data.compareTo(data) == 0) {
                return this;    //通过这个返回要删除的数据
            } else {
                if (this.data.compareTo(data) < 0) {
                    //返回的是无数次递归后的找到的数据,其实就是利用上面的return this返回数据;
                    return this.right.removeNode(data);
                } else {
                    return this.left.removeNode(data);
                }
            }
        }
    }
}

public class Demo01 {
    public static void main(String[] args) {
        Two<Member> two = new TwoImpl<>();
        two.add(new Member("孙七", 27));
        two.add(new Member("赵六", 26));
        two.add(new Member("王五", 25));
        two.add(new Member("张三", 23));
        two.add(new Member("李四1", 24));
        two.add(new Member("李四2", 55));
        two.add(new Member("李四3", 40));
        two.add(new Member("李四4", 38));
        two.add(new Member("李四5", 29));
        two.add(new Member("李四6", 21));
        two.add(new Member("李四7", 19));
        two.add(new Member("李四11", 62));
        two.add(new Member("李四8", 51));
        two.add(new Member("李四9", 34));
        two.add(new Member("李四10", 56));
        two.add(new Member("李四12", 72));
        two.add(new Member("李四13", 45));
        two.add(new Member("李四46", 46));
        two.add(new Member("李四14", 33));
        two.add(new Member("李四15", 31));
        //删除根节点
        two.remove(new Member("孙七", 27));
        //two.remove(new Member("李四3", 40));
        System.out.println(Arrays.toString(two.toArray()));
    }
}

结果:

[name='李四7, age=19
, name='李四6, age=21
, name='张三, age=23
, name='李四1, age=24
, name='王五, age=25
, name='赵六, age=26
, name='李四5, age=29
, name='李四15, age=31
, name='李四14, age=33
, name='李四9, age=34
, name='李四4, age=38
, name='李四3, age=40
, name='李四13, age=45
, name='李四46, age=46
, name='李四8, age=51
, name='李四2, age=55
, name='李四10, age=56
, name='李四11, age=62
, name='李四12, age=72
]
发布了61 篇原创文章 · 获赞 0 · 访问量 2196

猜你喜欢

转载自blog.csdn.net/sabstarb/article/details/104285107