📜  数据结构|平衡二叉搜索树|问题7(1)

📅  最后修改于: 2023-12-03 15:26:09.468000             🧑  作者: Mango

数据结构 | 平衡二叉搜索树 | 问题7

简介

平衡二叉搜索树也被称为 AVL 树,是一种既能支持快速查找又能支持动态数据集合的数据结构。它可以在 O(log n) 的时间内进行插入、查找和删除操作。问题7是指在 AVL 树中,查找节点的前驱和后继。

前驱和后继的定义

假设 AVL 树中存在节点 x,我们希望查找它的前驱和后继。

前驱:在 AVL 树中,比 x 小的最大节点称为 x 的前驱,如果不存在比 x 小的节点,则 x 没有前驱。

后继:在 AVL 树中,比 x 大的最小节点称为 x 的后继,如果不存在比 x 大的节点,则 x 没有后继。

解决方法

对于每个节点,我们可以保存它的前驱和后继节点信息。当插入或删除一个节点时,我们可以更新它的前驱和后继节点信息。

查找前驱节点

要查找 x 的前驱,我们可以进行以下操作:

  1. 如果 x 左子树非空,那么 x 的前驱就是左子树中最大的节点(即该节点的右子树为空)。
  2. 如果 x 左子树为空,那么我们向上递归找到第一个祖先节点,它的右子树包含 x。这个祖先节点就是 x 的前驱。
查找后继节点

要查找 x 的后继,我们可以进行以下操作:

  1. 如果 x 右子树非空,那么 x 的后继就是右子树中最小的节点(即该节点的左子树为空)。
  2. 如果 x 右子树为空,那么我们向上递归找到第一个祖先节点,它的左子树包含 x。这个祖先节点就是 x 的后继。
代码片段

下面是 C++ 实现的代码片段,其中 Node 类表示 AVL 树的节点:

class Node {
public:
    int val, height;
    Node *left, *right, *pre, *suc;
    Node(int val) {
        this->val = val;
        this->height = 1;
        this->left = this->right = NULL;
        this->pre = this->suc = NULL;
    }
};

// 更新节点的前驱和后继信息
void updatePreSuc(Node* root) {
    if (!root) return;
    // 更新右子树的最小节点为节点的后继
    if (root->right) {
        Node* p = root->right;
        while (p->left) p = p->left;
        root->suc = p;
    }
    // 更新左子树的最大节点为节点的前驱
    if (root->left) {
        Node* p = root->left;
        while (p->right) p = p->right;
        root->pre = p;
    }
    // 递归更新子节点的前驱和后继信息
    updatePreSuc(root->left);
    updatePreSuc(root->right);
}

在节点插入或删除的时候,我们可以使用上述代码来更新前驱和后继节点信息。在查找前驱或后继节点时,我们可以沿着 AVL 树的左右子树递归查找。如果节点的左子树非空,则一定能找到前驱节点;如果右子树非空,则一定能找到后继节点。如果左右子树都为空,我们需要向上递归查找祖先节点。