二叉排序树(Java)

二叉排序树定义

一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
【注】:以上的三种定义在不同的数据结构教材中均有不同的定义方式 但是都是正确的 在开发时需要根据不 同的需求进行选择

删除节点策略

removeA():
当待删除的节点有左右子树时,将其左子树加入到右子节点,其右子节点作为 parent的新子树

removeB():
当待删除的节点有左右子树时,将右子树的最小节点(也可以选左子树的最大节点)作为 parent的新子节点

Java代码

这里使用了lombok插件支持


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
// 测试类,removeA()
class TestA {
    public static void main(String[] args) {
        Integer[] a = new Integer[]{6, 4, 9, 7, 2, 5, 3, 8, 1, 0};
        BinarySortTree<Integer> sortTree = new BinarySortTree<>(a);

        sortTree.infixOrder();
        System.out.println("sortTree = " + sortTree);

        for (Integer integer : a) {
            System.out.println("removeA = " + integer);
            // 输出根节点
            sortTree.removeA(integer);
            sortTree.infixOrder();
            System.out.println("sortTree = " + sortTree);
        }

    }
}

// 测试类,removeb()
class TestB {
    public static void main(String[] args) {
        Integer[] a = new Integer[]{6, 4, 9, 7, 2, 5, 3, 8, 1, 0};
        BinarySortTree<Integer> sortTree = new BinarySortTree<>(a);

        sortTree.infixOrder();
        System.out.println("sortTree = " + sortTree);

        for (Integer integer : a) {
            sortTree.removeB(integer);
            System.out.println("removeB = " + integer);
            sortTree.infixOrder();
            System.out.println("sortTree = " + sortTree);
        }
    }
}

/**
 * Desc: 二叉排序树
 *
 * @author pikachu
 * @date: 2022/8/19 11:21
 */
@Data
@NoArgsConstructor
public class BinarySortTree<E extends Comparable<E>> {
    private Node root;

    public BinarySortTree(E[] data) {
        for (E item : data) {
            add(item);
        }
    }

    /**
     * Desc:    添加新元素 data
     *
     * @author pikachu
     */
    public void add(E data) {
        if (root == null) {
            root = new Node<>(data);
        } else {
            root.add(new Node<>(data));
        }
    }

    /**
     * Desc:    移除元素data(如果存在)
     *
     * @param data 待移除的元素
     * @author pikachu
     */
    public void removeA(E data) {
        if (root == null) {
            System.out.println("Tree is empty");
        } else {
            root.removeA(root, new Node<>(data));
        }
    }
/**
 * Desc:
 *
 * @param data  待移除的元素
 * @author pikachu
 */
    public void removeB(E data) {
        if (root == null) {
            System.out.println("Tree is empty");
        } else {
            root.removeB(root, new Node<>(data));
        }
    }

    /**
     * Desc:    中序遍历该子树(从小到大输出)
     *
     * @author pikachu
     */
    public void infixOrder() {
        if (root == null) {
            System.out.println("Tree is empty");
        } else {
            root.infixOrder();
            System.out.println();
        }
    }

    @Override
    public String toString() {
        return root == null ? "Tree is empty" : "root : " + root.data;
    }


    @Data
    private class Node<E extends Comparable<E>> {
        private Node<E> left;
        private Node<E> right;
        private E data;

        private Node(E data) {
            this.data = data;
        }

        /**
         * Desc:    将 node加入到当前节点 this
         *
         * @param node 待加入节点
         * @author pikachu
         */
        private void add(Node<E> node) {
            if (node.data.compareTo(this.data) <= 0) {
                if (this.left != null) {
                    this.left.add(node);
                } else {
                    this.left = node;
                }
            } else {
                if (this.right != null) {
                    this.right.add(node);
                } else {
                    this.right = node;
                }
            }
        }

        /**
         * Desc:移除preNode的子树中的node节点(如果存在),
         * 当待删除的节点有左右子树时,将其左子树加入到右子节点,其右子节点作为 parent的新子树
         *
         * @param parent  当前节点的父节点
         * @param delNode 待移除的节点
         * @author pikachu
         */
        private void removeA(Node parent, Node delNode) {
            //  1.delNode < this,往左子树查找删除;若左子树为空则结束
            if (delNode.data.compareTo(this.data) < 0) {
                if (this.left != null) {
                    this.left.removeA(this, delNode);
                }
            }
            //  2.delNode > this,往右子树查找删除;若右子树为空则结束
            else if (delNode.data.compareTo(this.data) > 0) {
                if (this.right != null) {
                    this.right.removeA(this, delNode);
                }
            }
            //  3.delNode = this 找到待删除的节点 this
            else if (delNode.data.compareTo(this.data) == 0) {

                //  3.1 this.right不为空,以this.right为新子树的根节点,将不为空的this.left加入该子树
                if (this.right != null) {
                    if (this.left != null) {
                        this.right.add(this.left);
                    }
                    //  3.1.1 待删除节点 this为 parent 左子节点
                    if (parent.left == this) {
                        parent.left = this.right;
                    }
                    //  3.1.2 待删除节点 this为 parent 右子节点
                    else if (parent.right == this) {
                        parent.right = this.right;
                    }
                    //  3.1.3 删除树中的根节点
                    else {
                        root = this.right;
                    }
                }
                //  3.2 this.right为空,类推
                else {
                    if (parent.left == this) {
                        parent.left = this.left;
                    } else if (parent.right == this) {
                        parent.right = this.left;
                    } else {
                        root = this.left;
                    }
                }
            }
        }

        /**
         * Desc:移除preNode的子树中的node节点(如果存在),
         * 当待删除的节点有左右子树时,将右子树的最小节点作为 parent的新子节点
         *
         * @param parent  当前节点的父节点
         * @param delNode 待删除节点
         * @author pikachu
         */
        private void removeB(Node<E> parent, Node<E> delNode) {
            //  1.delNode < this,往左子树查找删除;若左子树为空则结束
            if (delNode.data.compareTo(this.data) < 0) {
                if (this.left != null) {
                    this.left.removeB(this, delNode);
                }
            }
            //  2.delNode > this,往右子树查找删除;若右子树为空则结束
            else if (delNode.data.compareTo(this.data) > 0) {
                if (this.right != null) {
                    this.right.removeB(this, delNode);
                }
            }
            //  3.delNode = this 找到待删除的节点 this
            else if (delNode.data.compareTo(this.data) == 0) {
                //  3.1 this.right不为空,在 this.right的子树中寻找最小节点 rightMinNode,作为新子树的根节点
                if (this.right != null) {
                    Node<E> preNode = this;
                    Node<E> rightMinNode = preNode.right;
                    while (rightMinNode.left != null) {
                        preNode = rightMinNode;
                        rightMinNode = rightMinNode.left;
                    }
                    //
                    if (preNode.right != rightMinNode) {
                        preNode.left = rightMinNode.right;
                    } else {
                        preNode.right = preNode.right.right;
                    }
                    this.data = rightMinNode.data;
                }
                // 3.2 this.right为空
                else {
                    if (this == parent.right) {
                        parent.right = this.left;
                    } else if (this == parent.left) {
                        parent.left = this.left;
                    }
                    // 3.2.1 删除树中根节点
                    else {
                        root = root.left;
                    }
                }
            }
        }

        /**
         * Desc:
         * 中序遍历二叉排序树后刚好从小到大输出
         *
         * @author pikachu
         */
        private void infixOrder() {
            if (this.left != null) {
                this.left.infixOrder();
            }
            System.out.print(this.data + " -> ");
            if (this.right != null) {
                this.right.infixOrder();
            }
        }

        @Override
        public String toString() {
            return this.data.toString();
        }
    }
}

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
class Emp implements Comparable<Emp> {
    private int no;
    private String name;

    @Override
    public int compareTo(Emp o) {
        return this.no - o.no;
    }
}

运行测试

若存在疏漏,欢迎指正。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值