BST二叉排序树

BST二叉排序树:又称二叉查找树,它是一种对排序和查找都很有用的特殊二叉树;满足data.key > lchild.key > data.key,即节点值大于左子树值小于右子树值;
BST二叉排序树很多高级数据结构和算法的基础,比如AVL平衡二叉树、Red-Black红黑树...

 以下demo基本包含了BST二叉排序树的添加、删除、查找、前序遍历(递归和非递归)、中序遍历(递归和非递归)、后续遍历(递归和非递归)、按层级从上到下遍历...方法:

demo中用到的测试用例数据

节点类 TreeNode.java

/**
 * @Author: ltx
 * @Description: BST二叉树节点
 */
public class TreeNode {
    public Integer value;//节点值
    public TreeNode left;//左子节点
    public TreeNode right;//右子节点

    public TreeNode(Integer value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return String.valueOf(value);
    }
}

BST二叉排序树类 BinarySortTree.java

/**
 * @Author: ltx
 * @Description:
 */
public class BinarySortTree {
    public TreeNode root;//根节点;

    /**
     * 初始化BST树
     *
     * @param arr 树的元素
     * @return
     */
    public static BinarySortTree initBSTTree(int[] arr) {
        BinarySortTree binarySortTree = new BinarySortTree();
        for (int value : arr) {
            binarySortTree.addBSTNode(new TreeNode(value));
        }
        return binarySortTree;
    }

    /**
     * 前序
     */
    public void preOrder(TreeNode node) {
        System.out.print(node + ", ");
        if (node.left != null) {
            preOrder(node.left);
        }
        if (node.right != null) {
            preOrder(node.right);
        }
    }

    /**
     * 前序-非递归实现
     */
    public void preOrderNoRecursion(TreeNode node) {
        Stack<TreeNode> st = new Stack<>();
        TreeNode temp = node;
        st.push(temp);
        while (!st.isEmpty()) {
            temp = st.pop();
            if (temp.right != null) {
                st.push(temp.right);
            }
            if (temp.left != null) {
                st.push(temp.left);
            }
            System.out.print(temp + ", ");
        }
    }

    /**
     * 中序
     */
    public void midOrder(TreeNode node) {
        if (node.left != null) {
            midOrder(node.left);
        }
        System.out.print(node + ", ");
        if (node.right != null) {
            midOrder(node.right);
        }
    }

    /**
     * 中序-非递归实现
     */
    public void midOrderNoRecursion(TreeNode node) {
        Stack<TreeNode> st = new Stack<>();
        TreeNode temp = node;
        while (temp != null || !st.isEmpty()) {
            //一直往左边遍历走到底放栈中
            while (temp != null) {
                st.push(temp);
                temp = temp.left;
            }
            //左边到底之后打印当前栈顶元素,再往右边走一下
            if (!st.isEmpty()) {
                //出栈
                temp = st.pop();
                System.out.print(temp + ", ");
                //往右走
                temp = temp.right;
            }
        }
    }

    /**
     * 后序
     */
    public void postOrder(TreeNode node) {
        if (node.left != null) {
            postOrder(node.left);
        }
        if (node.right != null) {
            postOrder(node.right);
        }
        System.out.print(node + ", ");
    }

    /**
     * 后序-非递归实现
     * 原理-逆后续遍历,基于前序遍历调转左右子节点,当前->右->左,然后再反转,
     */
    public void postOrderNoRecursion(TreeNode node) {
        Stack<TreeNode> st1 = new Stack<>();
        Stack<TreeNode> st2 = new Stack<>();
        TreeNode temp = node;
        st1.push(temp);
        while (!st1.isEmpty()) {
            temp = st1.pop();
            if (temp.left != null) {
                st1.push(temp.left);
            }
            if (temp.right != null) {
                st1.push(temp.right);
            }
            st2.push(temp);
        }
        while (!st2.isEmpty()) {
            System.out.print(st2.pop() + ", ");
        }
    }

    /**
     * 按层级从上到下遍历
     * 原理:利用队列,类似图的广度优先遍历
     */
    public void tierTraverse(TreeNode node) {
        Queue<TreeNode> ls = new LinkedList();
        ls.add(node);
        while (!ls.isEmpty()) {
            TreeNode temp = ls.remove();
            if (temp.left != null) {
                ls.add(temp.left);
            }
            if (temp.right != null) {
                ls.add(temp.right);
            }
            System.out.print(temp + ", ");
        }
    }


    /**
     * 添加元素-BST树添加节点
     *
     * @param node    添加元素的节点
     * @param element 要添加的节点
     * @return
     */
    public TreeNode addBSTNode(TreeNode node, TreeNode element) {
        //root节点为空,则直接返回要添加的节点
        if (node == null) {
            return element;
        }
        if (element.value < node.value) {
            if (node.left == null) {
                node.left = element;
            } else {
                //递归回溯赋值
                node.left = addBSTNode(node.left, element);
            }
        } else {
            //右边空切值大于等于节点
            if (node.right == null) {
                node.right = element;
            } else {
                //递归回溯赋值
                node.right = addBSTNode(node.right, element);
            }
        }
        return node;
    }

    /**
     * 查找
     *
     * @param value 要查找的节点值
     * @param node  从哪个节点开始找, 一般是root节点
     * @return
     */
    public TreeNode search(Integer value, TreeNode node) {
        if (node == null) {
            System.out.println("未找到!");
            return null;
        }
        if (node.value.equals(value)) {
            System.out.println("找到: " + node);
            return node;
        }
        if (value < node.value) {
            if (node.left != null) {
                //继续从左边找
                return search(value, node.left);
            } else {
                System.out.println("未找到!");
                return null;
            }
        } else {
            if (node.right != null) {
                //继续从右边找
                return search(value, node.right);
            } else {
                System.out.println("未找到!");
                return null;
            }
        }
    }

    /**
     * node节点的树高
     *
     * @param node 节点
     * @return
     */
    public int getHeight(TreeNode node) {
        int leftHeight = 0;
        if (node.left != null) {
            leftHeight = getHeight(node.left);
        }
        int rightHeight = 0;
        if (node.right != null) {
            rightHeight = getHeight(node.right);
        }
        return Math.max(leftHeight, rightHeight) + 1;
    }

    /**
     * BST删除节点
     *
     * @param value      要查找的节点值
     * @param node       节点
     * @param parentNode 要查找节点的父节点(顺便获取查找节点父节点, 方便删除节点使用)
     * @return
     */
    public TreeNode deleteBSTNode(Integer value, TreeNode node, TreeNode parentNode) {
        if (node.value.equals(value)) {
            System.out.printf("找到, targetNode: %s, parentNode: %s\n", node, parentNode);
            //这里返回的是被删除节点的位置
            return deleteNode(node, parentNode);
        }
        if (value < node.value) {
            if (node.left != null) {
                //这里的node是父节点
                node.left = deleteBSTNode(value, node.left, node);
            } else {
                System.out.println("未找到!");
                return null;
            }
        } else {
            if (node.right != null) {
                //这里的node是父节点
                node.right = deleteBSTNode(value, node.right, node);
            } else {
                System.out.println("未找到!");
                return null;
            }
        }
        return node;
    }

    /**
     * 删除节点
     * 首先找到删除节点 targetNode 和它的父节点 parentNode
     * 节点的3中情况处理:
     * 1.targetNode是叶子节点;
     * if targetNode是parentNode的左子节点, 则 parentNode.left = null;
     * if targetNode是parentNode的右子节点, 则 parentNode.right = null;
     * 2.targetNode有1颗子树
     * if targetNode有左子树,targetNode是parentNode的左子节点, 则 parentNode.left = targetNode.left;
     * if targetNode有右子树,targetNode是parentNode的左子节点, 则 parentNode.left = targetNode.right;
     * if targetNode有左子树,targetNode是parentNode的右子节点, 则 parentNode.right = targetNode.left;
     * if targetNode有右子树,targetNode是parentNode的右子节点, 则 parentNode.right = targetNode.right;
     * 3.targetNode有2颗子树;
     * 左子树的最大节点(或者右子树中最小的节点) maxNode;
     * 删除maxNode;
     * (简单的对象,可以用 targetNode.value=maxNode.value 直接替代下面4步)
     * maxNode.left = targetNode.left;
     * maxNode.right = targetNode.right;
     * if targetNode是parentNode的左子节点, 则 parentNode.left = maxNode;
     * if targetNode是parentNode的右子节点, 则 parentNode.right = maxNode;
     *
     * @param targetNode 删除目标节点
     * @param parentNode 删除目标节点的父节点
     * @return 注意:这里返回的是被删除节点的位置
     */
    public TreeNode deleteNode(TreeNode targetNode, TreeNode parentNode) {
        if (targetNode == null) {
            //没有找到要删除的节点直接返回false
            System.out.println("没有找到要删除的节点...");
        }
        System.out.printf("targetNode: %s, parentNode: %s\n", targetNode, parentNode);
        /**
         * 1.targetNode是叶子节点;
         */
        if (targetNode.left == null && targetNode.right == null) {
            if (parentNode.left != null && parentNode.left.value.equals(targetNode.value)) {
                //targetNode在左
                parentNode.left = null;
            } else if (parentNode.right != null && parentNode.right.value.equals(targetNode.value)) {
                //targetNode在右
                parentNode.right = null;
            }
            return null;
        } else if (targetNode.left != null || targetNode.right != null) {
            /**
             * 2.targetNode有1颗子树
             */
            if (targetNode.left != null && targetNode.right == null) {
                //targetNode有1个左子树
                if (parentNode.left != null && parentNode.left.value.equals(targetNode.value)) {
                    //targetNode在左
                    parentNode.left = targetNode.left;
                } else if (parentNode.right != null && parentNode.right.value.equals(targetNode.value)) {
                    //targetNode在右
                    parentNode.right = targetNode.left;
                }
                return targetNode.left;
            } else if (targetNode.right != null && targetNode.left == null) {
                //targetNode有1个右子树
                if (parentNode.left != null && parentNode.left.value.equals(targetNode.value)) {
                    //targetNode在parentNode左
                    parentNode.left = targetNode.right;
                } else if (parentNode.right != null && parentNode.right.value.equals(targetNode.value)) {
                    //targetNode在parentNode右
                    parentNode.right = targetNode.right;
                }
                return targetNode.right;
            } else if (targetNode.left != null && targetNode.right != null) {
                /**
                 * 3.targetNode有2颗子树;
                 */
                //删除左边最大节点并返回
                TreeNode maxNode = deleteMaxNode(targetNode.left, targetNode);
                //最大节点值赋值到当前节点位置
                targetNode.value = maxNode.value;
                return targetNode;
            }
        }
        return null;
    }

    /**
     * 删除树最大节点
     * 最大节点-一直往右边找。最右边的节点就是该树的最大节点
     *
     * @param
     * @return maxNode
     */
    public TreeNode deleteMaxNode(TreeNode temp, TreeNode parentNode) {
        while (temp.right != null) {
            parentNode = temp;
            temp = temp.right;
        }
        //右子树中最大的节点 maxNode
        TreeNode maxNode = temp;
        //删除最大节点
        deleteBSTNode(maxNode.value, maxNode, parentNode);
        return maxNode;
    }

    /**
     * BST添加元素
     *
     * @param node
     */
    public void addBSTNode(TreeNode node) {
        root = addBSTNode(root, node);
    }

    /**
     * 遍历tree
     */
    public void show() {
        if (root != null) {
            System.out.println("前序:");
            preOrder(root);
            System.out.println();
            System.out.println("前序(非递归):");
            preOrderNoRecursion(root);
            System.out.println();
            System.out.println("中序:");
            midOrder(root);
            System.out.println();
            System.out.println("中序(非递归):");
            midOrderNoRecursion(root);
            System.out.println();
            System.out.println("后序:");
            postOrder(root);
            System.out.println();
            System.out.println("后序(非递归):");
            postOrderNoRecursion(root);
            System.out.println();
            System.out.println("按层级从上到下遍历:");
            tierTraverse(root);
            System.out.println();
        } else {
            System.out.println("树为null");
        }
    }

    /**
     * 查找元素
     *
     * @param value
     * @return
     */
    public TreeNode search(Integer value) {
        return search(value, root);
    }

    /**
     * BST删除元素
     *
     * @param value
     * @return
     */
    public Boolean deleteBSTNode(Integer value) {
        root = deleteBSTNode(value, root, null);
        return true;
    }

    public static void main(String[] args) {
        //初始化一个树
        int[] arr = {7, 3, 8, 10, 12, 5, 1, 9, 2, 6, 4};
        BinarySortTree binarySortTree = BinarySortTree.initBSTTree(arr);
        //前中后序遍历节点
//        binarySortTree.show();
//        System.out.println("搜索: ");
//        binarySortTree.search(9);
//        System.out.println("树高: ");
//        System.out.println(binarySortTree.getHeight(binarySortTree.root));
        System.out.println("中序:");
        binarySortTree.midOrder(binarySortTree.root);
        System.out.println();
        System.out.println("删除节点: ");
//        binarySortTree.deleteAVLNode(9);
        binarySortTree.deleteBSTNode(8);
//        binarySortTree.deleteBSTNode(3);
//        binarySortTree.deleteNode(2);
        System.out.println("中序:");
        binarySortTree.midOrder(binarySortTree.root);
        System.out.println();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小绿豆

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值