二叉排序树

二叉排序树

   二叉排序树: (Binary Sort Tree),对于二叉排序树的任何一个非叶子节点,要求左子节点的值小于等于当前节点的值,右子节点的值大于等于当前节点的值。

将序列 {7, 3, 10, 12, 5, 1, 9, 2} 构造成而二叉排序树举例说明:

添加操作

在这里插入图片描述
步骤:

  1.   添加 7 :7 作为根结点
  2.   添加 3 :3 比 7 小且 7 的左子节点为空,作为 7 的左子节点
  3.   添加 7 :10 比 7 大且 7 的右子节点为空,作为 7 的右子节点
  4.   添加 7 :12 比 7 大,又比 10 大且 10 的右子节点为空,作为 10 的右子节点
  5.   添加 7 :5 比 7 小,放在 7 的左边,又比 3 大且 3 的右子节点为空,作为 3 的右子节点
  6.   添加 7 :1 比 7 小,放在 7 的左边,又比 3 小且 3 的左子节点为空,作为 3 的左子节点
  7.   添加 7 :9 比 7 大,放在 7 的右边,又比 10 小且 10 的左子节点为空,作为 10 的左子节点。
  8.   添加 7 :2 比 7 小,放在 7 的左边,又比 3 小,放在 3 的左边,又比 1 大且 1 的右子节点为空,作为 1 的右子节点。

删除操作

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

  1. 删除叶子节点(比如:2, 5, 9, 12)
    (1) 需求先去找到要删除的结点 targetNode
    (2) 找到 targetNode 的父结点 targetparentNode
    (3) 如果 targetNode 是 targetparentNode 的左子结点就 targetparentNode.left = null,如果是右子结点就 targetparentNode.right = null

  2. 删除只有一颗子树的节点(比如: 1)
    2.1 先找到要删除的结点 targetNode
    2.2 找到 targetNode 的父结点 targetparentNode
    2.3 确定 targetNode 的子结点是左子结点还是右子结点
    2.4 targetNode 是 targetparentNode 的左子结点还是右子结点
    2.5 如果 targetNode 的子结点是左子结点:
     2.5.1 如果 targetNode 是 targetparentNode 的左子结点 targetparentNode.left = targetNode.left
     2.5.2 如果 targetNode 是 targetparentNode 的右子结点 targetparentNode.right = targetNode.left
    2.6 如果 targetNode 的子结点是右子结点
     2.6.1 如果 targetNode 是 targetparentNode 的左子结点targetparentNode.left = targetNode.right
     2.6.2如果 targetNode 是 targetparentNode 的右子结点 targetparentNode.right = targetNode.right

  3. 删除有两颗子树的节点.(比如:7, 3,10 )
    3.1 先找到要删除的结点 targetNode
    3.2 找到 targetNode 的父结点 targetparentNode
    3.3 从 targetNode 的右子树找到最小的结点
    3.4 删除该最小结点并将值赋值给 targetNode.value

结点

class Node {
    int value;
    Node left;
    Node right;

    public Node(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return value + "    ";
    }

    // 向二叉排序树中添加结点
    public void add(Node node) {
        if (node == null) {
            return;
        }
        // 添加的结点小于当前结点
        if (node.value < this.value) {
            if (this.left == null) {
                this.left = node;
            } else { // 向左边递归添加
                this.left.add(node);
            }
        } else { // 添加的结点大于当前结点
            if (this.right == null) {
                this.right = node;
            } else { // 向右边递归添加
                this.right.add(node);
            }
        }
    }

    // 查找要删除的结点
    public Node search(int value) {
        if (this.value == value) {
            return this;
        } else if (value < this.value) { // 左子树递归查找
            if (this.left != null) {
                return this.left.search(value);
            } else { // 找不到该结点
                return null;
            }
        } else { // 右子树递归查找
            if (this.right != null) {
                return this.right.search(value);
            } else { // 找不到该结点
                return null;
            }
        }
    }

    // 查找要删除的结点的父节点
    public Node searchParent(int value) {
        if ((this.left != null && this.left.value == value) || (this.right != null && this.right.value == value)) {
            return this;
        } else {
            if (value < this.value && this.left != null) { // 左子树递归查找
                return this.left.searchParent(value);
            } else if (value > this.value && this.right != null) {  // 右子树递归查找
                return this.right.searchParent(value);
            } else { // 找不到父节点
                return null;
            }
        }
    }

    // 中序遍历
    public void infixOrder() {
        if (this.left != null) {
            this.left.infixOrder();
        }
        System.out.print(this);
        if (this.right != null) {
            this.right.infixOrder();
        }
    }
}

二叉排序树

class BinarySortTree {
    private Node root;

    // 向二叉排序树中添加结点法
    public void add(Node node) {
        if (root != null) {
            root.add(node);
        } else {
            root = node;
        }
    }

    // 查找要删除的结点
    public Node search(int value) {
        if (root == null) { // 空树
            return null;
        } else {
            return root.search(value);
        }
    }

    // 查找要删除的结点的父节点
    public Node searchParent(int value) {
        if (root == null) { // 空树
            return null;
        } else {
            return root.searchParent(value);
        }
    }

    /**
     * @description:  删除右子树最小的结点
     * @Param: node 以 node 为根节点的树中最小的值
     */
    public int delRightTreeMin(Node node) {
       Node temp = node;
       while (temp.left != null) { // 找最小的值
           temp = temp.left;
       }
       delNode(temp.value); // 删除这个最小的结点
       return temp.value; // 返回这个最小的结点的 value
    }

    // 删除结点
    public void delNode(int value) {
        if (root == null) {
            return;
        }
        // 不是空树
        // 找到要删除的结点
        Node targeNode = search(value);
        // 如果没有找到要删除的结点
        if (targeNode == null) {
            return;
        }
        // 如果要删除的结点是唯一的结点
        if (root.left == null && root.right == null) {
            root = null;
            return;
        }
        // 找到要删除的结点的父节点
        Node targeParentNode = searchParent(value);
        // 如果要删除的结点是叶子结点
        if (targeNode.left == null && targeNode.right == null) {
            if (targeParentNode.left == targeNode) { // 如果要删除的结点是左子结点
                targeParentNode.left = null;
            } else { // 如果要删除的结点是右子结点
                targeParentNode.right = null;
            }
        } else if (targeNode.left != null && targeNode.right != null) { // 如果要删除的结点有两个子结点
            // 此处当前结点替换为右子树中最小值并删除右子树中最小值,也可以替换为左子树中最大值并删除左子树最大值
            targeNode.value = delRightTreeMin(targeNode.right);
        } else { // 如果要删除的结点只有一个子结点
            // 如果删除的结点只有左子树
            if (targeNode.left != null) {
                if (targeParentNode == null) { // 如果是根结点, 直接移动根结点
                    root = targeNode.left;
                    return;
                }
                if (targeParentNode.left == targeNode) { // 如果该结点是父节点的左结节点
                    targeParentNode.left = targeNode.left;
                } else {  // 如果该结点是父节点的右结节点
                    targeParentNode.right = targeNode.left;
                }
            } else { // 如果删除的结点只有右子树
                if (targeParentNode == null) { // 如果是根结点, 直接移动根结点
                    root = targeNode.right;
                    return;
                }
                if (targeParentNode.left == targeNode) { // 如果该结点是父节点的左结节点
                    targeParentNode.left = targeNode.right;
                } else { // 如果该结点是父节点的右结节点
                    targeParentNode.right = targeNode.right;
                }
            }
        }
    }

    // 中序遍历
    public void infixOrder() {
        if (root != null) {
            root.infixOrder();
        } else {
            System.out.println("空树");
        }
    }
}

二叉排序树演示

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.add(new Node(arr[i]));
        }
        /* 该二叉排序树大致如下
                        7
                   *         *
                3              10
              *   *          *    *
            1       5       9      12
             *
              2
        */
        System.out.println("-------------------中序遍历--------------------");
        binarySortTree.infixOrder();
        System.out.println();

        // 删除叶子结点
        binarySortTree.delNode(12);
        System.out.println("---------------删除叶子结点 12 -----------------");
        binarySortTree.infixOrder();
        System.out.println();

        // 删除只有一个子结点的结点
        binarySortTree.delNode(1);
        System.out.println("------------删除只有一个子结点的结点 1 -----------");
        binarySortTree.infixOrder();
        System.out.println();

        // 删除有两个子结点的结点
        binarySortTree.delNode(3);
        System.out.println("------------删除有两个子结点的结点 3 -------------");
        binarySortTree.infixOrder();
        System.out.println();

        // 删除根结点
        binarySortTree.delNode(7);
        System.out.println("---------------删除根结点 7 -------------------");
        binarySortTree.infixOrder();
        System.out.println();

        // 全部删除
        binarySortTree.delNode(2);
        binarySortTree.delNode(5);
        binarySortTree.delNode(9);
        binarySortTree.delNode(10);
        System.out.println("----------------全部删除-----------------------");
        binarySortTree.infixOrder();
    }
}

运行结果

-----------------中序遍历------------------
1    2    3    5    7    9    10    12
-----------------删除叶子结点 12 ------------------
1    2    3    5    7    9    10
-----------------删除只有一个子结点的结点 1 ------------------
2    3    5    7    9    10
-----------------删除有两个子结点的结点 3 ------------------
2    5    7    9    10
-----------------删除根结点 7 ------------------
2    5    9    10
-----------------全部删除------------------
空树
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值