📜  门| GATE CS Mock 2018年|套装2 |第58章(1)

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

门 GATE CS 模拟考试 2018 | 套装 2 | 第 58 题

这是 2018 年 GATE 计算机科学模拟考试套装 2 的第 58 题。本题考查的是二叉搜索树(BST)的基本操作。

题目描述

实现一个函数 delete_key,删除给定二叉搜索树中的一个键。该函数应接受两个参数:一个指向 BST 根节点的指针 root,以及要删除的键 key。函数应返回指向修改后 BST 根节点的指针。

函数原型如下:

BSTNode* delete_key(BSTNode* root, int key);

你可以假设在给定的 BST 中仅有一个键与 key 相等。

输入格式

函数最开始接收的 root 指针指向的 BST 的样本输入数据格式如下(每个节点占据一行):

k1
/k \
   k2
  / \
 k3  k4

其中每个 k 代表一个整数键,/\ 表示指针。

输出格式

函数返回指向修改后 BST 根节点的指针,输出格式与输入格式相同。

样例 1

输入:

50
/  \
30  70
   /  \
  60  80

要删除键 50

输出:

60
/ \
30 70
 \  \
  80
样例 2

输入:

20
/  \
10  30
   / \
  25 35

要删除键 30

输出:

20
/  \
10  35
   /
  25
解题思路

由于本题考察 BST 的常见操作之一,因此我们需要对 BST 的特点和常见操作有足够的了解。

对于 BST 中的任何节点都满足以下两个条件:

  1. 该节点上所有左侧子节点都小于该节点;
  2. 该节点上所有右侧子节点都大于该节点。

由此可以推出:BST 的中序遍历是有序的。

因此,我们可以考虑分两种情况来处理待删除的键:

  1. 待删除键是叶节点:直接删除即可。
  2. 待删除键有一个子节点:删除该键,并将其子节点上移到该键的位置。
  3. 待删除键有两个子节点:找到其右子树中最小的键 min,将其替换待删除键的位置,然后删除 min

具体实现细节见代码片段。

代码实现
struct BSTNode {
    int key;
    BSTNode *left, *right;
};

BSTNode* delete_key(BSTNode* root, int key) {
    if (root == nullptr) {
        return nullptr;
    }
    if (root->key > key) {
        root->left = delete_key(root->left, key);
    } else if (root->key < key) {
        root->right = delete_key(root->right, key);
    } else {
        if (root->left == nullptr) {
            BSTNode* temp = root->right;
            delete root;
            root = temp;
        } else if (root->right == nullptr) {
            BSTNode* temp = root->left;
            delete root;
            root = temp;
        } else {
            BSTNode* temp = root->right;
            while (temp->left != nullptr) {
                temp = temp->left;
            }
            root->key = temp->key;
            root->right = delete_key(root->right, temp->key);
        }
    }
    return root;
}

上述代码实现了 delete_key 函数。其时间复杂度为 $O(h)$,其中 $h$ 为树的高度。由于 BST 的性质,$h$ 的最坏情况为 $O(n)$(即树退化为链表),因此该函数最坏情况下的时间复杂度为 $O(n)$。