二叉排序树(二叉搜索树)

二叉排序树(也称为二叉查找树)是一种特殊的二叉树,它可以用来快速查找、插入和删除节点。

二叉排序树有以下性质:

  1. 在二叉排序树中,左子节点的值总是小于父节点的值。
  2. 在二叉排序树中,右子节点的值总是大于父节点的值。
  3. 二叉排序树的中序遍历结果是一个单调递增的序列。

在这个例子中,我们定义了两个类:Node 类和 BinarySearchTree 类。Node 类表示二叉排序树中的一个节点,包含一个数据域和两个指针域。BinarySearchTree 类表示二叉排序树本身,包含根节点和一些操作方法。

这个类实现了二叉排序树的两个常用操作:插入和查找。插入操作使用递归实现,查找操作也是使用递归实现。

下面是java实现的版本

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

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

class BinarySearchTree {
    Node root;

    public BinarySearchTree() {
        root = null;
    }

    public void insert(int value) {
        root = insertRecursive(root, value);
    }

    private Node insertRecursive(Node current, int value) {
        if (current == null) {
            return new Node(value);
        }

        if (value < current.value) {
            current.left = insertRecursive(current.left, value);
        } else if (value > current.value) {
            current.right = insertRecursive(current.right, value);
        } else {
            return current;
        }

        return current;
    }

    public boolean search(int value) {
        return searchRecursive(root, value);
    }

    private boolean searchRecursive(Node current, int value) {
        if (current == null) {
            return false;
        }
        if (value == current.value) {
            return true;
        }
        return value < current.value
          ? searchRecursive(current.left, value)
          : searchRecursive(current.right, value);
    }
}


        首先来看一下插入操作的流程

        参数value为待插入的元素值,current为当前树的根节点

  1. 首先,如果当前节点为空,说明已经到达了二叉排序树的叶子节点,此时可以直接创建新节点并返回。
  2. 否则,如果新值小于当前节点的值,则递归调用 insertRecursive 方法,将新值插入到当前节点的左子树中。
  3. 如果新值大于当前节点的值,则递归调用 insertRecursive 方法,将新值插入到当前节点的右子树中。
  4. 如果新值等于当前节点的值,则直接返回当前节点,

查找操作

  1. 首先,如果当前节点为空,说明已经搜索到了二叉排序树的叶子节点,此时可以返回 false
  2. 否则,如果搜索的值等于当前节点的值,则返回 true
  3. 否则,如果搜索的值小于当前节点的值,则递归调用 searchRecursive 方法,在当前节点的左子树中继续搜索。
  4. 否则,递归调用 searchRecursive 方法,在当前节点的右子树中继续搜索。

删除操作(重点)

public Node deleteNode(Node root, int key) {
    if (root == null) {
        return null;
    }
    if (key < root.value) {
        root.left = deleteNode(root.left, key);
    } else if (key > root.value) {
        root.right = deleteNode(root.right, key);
    } else {
        if (root.left == null) {
            return root.right;
        } else if (root.right == null) {
            return root.left;
        }
        root.value = minValue(root.right);
        root.right = deleteNode(root.right, root.value);
    }
    return root;
}

在这个例子中,我们定义了一个名为 deleteNode 的方法,它接受两个参数:根节点和要删除的结点的值。方法体内部实现了删除结点的逻辑。

这段代码的工作流程如下:

  1. 首先,如果根节点为空,则返回空。
  2. 如果要删除的结点的值小于根节点的值,则递归调用 deleteNode 方法,在根节点的左子树中继续查找要删除的结点。
  3. 如果要删除的结点的值大于根节点的值,则递归调用 deleteNode 方法,在根节点的右子树中继续查找要删除的结点。
  4. 如果要删除的结点的值等于根节点的值,则执行删除操作。
  5. 如果根节点没有左子树,则返回右子树。
  6. 如果根节点没有右子树,则返回左子树。
  7. 否则,找到右子树中最小的结点,并将这个结点的值赋值给根节点。然后递归调用 deleteNode 方法,在根节点的右子树中删除这个最小结点。

删除操作中用到了一个查找子树最小结点值的方法

private int minValue(Node node) {
    int minv = node.value;
    while (node.left != null) {
        minv = node.left.value;
        node = node.left;
    }
    return minv;
}

这段代码的工作流程如下:

首先,将最小值初始化为当前结点的值。

  1. 循环遍历当前结点的左子树,直到找到最小的结点。
  2. 返回最小的结点的值。

同样的,我们也可以实现查找二叉排序树的最大值的方法。这个方法的实现方式与查找最小值的方法类似,只是将最小值换成最大值即可。

最后,来看一下二叉排序树的应用案例

  1.  在数据库的索引中,二叉排序树可以用来快速查找数据。二叉排序树的查找时间复杂度为 O(log n),要比顺序查找的时间复杂度 O(n) 快得多。
  2. 二叉排序树还常用于实现字典树(Trie)。字典树是一种树形数据结构,用来存储字符串集合。它的每个结点都包含一个字符,并且满足二叉排序树的性质:左子树的结点代表的字符都比根节点小,右子树的结点代表的字符都比根节点大。因此,我们可以使用二叉排序树来实现字典树。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值