漫谈数据结构——二叉查找树(下)

118 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

前言

在上一篇文章中,我们了解了二叉查找树的概念,以及如何对一个二叉查找树进行查找操作,插入操作。在熟悉概念的情况下,这两种操作比较容易理解。使用代码实现也相对比较简单。那么我们今天要介绍就是比较复杂的操作——删除操作。

二叉查找树的删除操作

二叉查找树的删除操作需要分为三种情况进行分析。

  1. 第一种情况是,如果需要删除的节点没有子节点,那么我们直接父节点下引用该节点的变量设置为空即可。
  2. 第二种情况是,如果要删除的节点有一个子节点(左子节点或者右子节点),我们只需要把指向删除节点的指针引用,修改成指向该子节点的引用即可。
  3. 第三种情况是删除的节点下有两个节点,左子节点和右子节点。首先我们需要在该删除节点的右子树中,去寻找最小节点,将其替换到删除节点的位置上,然后再运用前面两种情况,对这个最小节点进行分析即可。这样就可以删除掉拥有两个子节点的节点了。 以下我们展示一下删除操作的代码:
public void delete(int data) {
    Node p = tree;
    Node pp = null;
    while (p != null && p.data != data) {
        pp = p;
        if (data > p.data) {
            p = p.right;
        } else {
            p.left;
        }
    }

    if (p == null) {
        return;
    }

    if (p.left != null && p.right != null) {
        Node minP = p.right;
        Node minPP = p;
        while (minP.left != null) {
            minPP = minP;
            minP = minPP.left;
        }

        p.data = minPP.data;
        p = minP;
        pp = minPP;
    }

    Node child = null;
    if (p.left != null) {
        child = p.left;
    } else if (p.right != null) {
        child = p.right;
    }

    if (pp == null) {
        tree = child;
    } else if (pp.left == p) {
        pp.left = child;
    } else {
        pp.right = child;
    }

}

二叉查找树的时间复杂度分析

因为二叉树查找有多种形态,假如一个二叉查找树的根节点的左右子树极度不平衡,那么就会退化成链表的形式,所以此时的时间复杂度则变为O(n)。

如果二叉查找树的状态是平衡二叉查找树,树的高度接近logn,所以这种情况下时间复杂度是O(logn)

总结

本文中我们分析了二叉查找树最复杂的操作,删除操作以及时间复杂度的分析。