📜  门|门 CS 1997 |问题 16(1)

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

门门 CS 1997 问题 16

简介

门门 CS 1997问题16是一个蓝题目,考察了代码实现的基本技能和思维能力。题目要求实现一种数据结构,支持以下操作:

  1. 插入元素
  2. 删除元素
  3. 查询某个元素是否存在
  4. 查询最小的大于某个元素的元素
  5. 查询最大的小于某个元素的元素
实现思路

本题可以使用平衡树实现,常用的平衡树种类有红黑树和AVL树。它们都能够在O(logn)的时间复杂度内完成以上操作。

我们可以按照以下步骤实现:

  1. 定义平衡树节点结构体,包含以下成员变量:key(节点的键值),left(左儿子指针),right(右儿子指针),height(节点高度)。
  2. 编写插入元素操作。在插入元素时,通过递归地向下搜索找到该元素应该插入到的位置,并计算出每个节点的高度,最后旋转以保持平衡。
  3. 编写删除元素操作。在删除元素时,先通过递归地向下搜索找到该元素所在的位置,并删除该节点。删除后需要检查并调整剩下节点的平衡。
  4. 编写查询某个元素是否存在的操作。与插入和删除类似,通过递归地向下搜索找到该元素所在的位置,如果找到则返回true,否则返回false。
  5. 编写查询最小的大于某个元素的元素操作。先找到该元素所在的位置,如果该节点存在右儿子,则返回右子树中最小的元素;否则,沿着父节点往上搜索,一直找到第一个比该元素大的节点。
  6. 编写查询最大的小于某个元素的元素操作。与查询最小的大于某个元素的元素操作类似,沿着父节点往上搜索,一直找到第一个比该元素小的节点。
代码实现
struct Node {
    int key, height;
    Node* left, *right;
    Node(int x) : key(x), height(1), left(nullptr), right(nullptr) {}
};

int height(Node* p) {
    return p ? p->height : 0;
}

int balanceFactor(Node* p) {
    return height(p->right) - height(p->left);
}

void fixHeight(Node* p) {
    int hl = height(p->left);
    int hr = height(p->right);
    p->height = (hl > hr ? hl : hr) + 1;
}

Node* rotateRight(Node* p) {
    Node* q = p->left;
    p->left = q->right;
    q->right = p;
    fixHeight(p);
    fixHeight(q);
    return q;
}

Node* rotateLeft(Node* q) {
    Node* p = q->right;
    q->right = p->left;
    p->left = q;
    fixHeight(q);
    fixHeight(p);
    return p;
}

Node* balance(Node* p) {
    fixHeight(p);
    if (balanceFactor(p) == 2) {
        if (balanceFactor(p->right) < 0)
            p->right = rotateRight(p->right);
        return rotateLeft(p);
    }
    if (balanceFactor(p) == -2) {
        if (balanceFactor(p->left) > 0)
            p->left = rotateLeft(p->left);
        return rotateRight(p);
    }
    return p;
}

Node* insert(Node* root, int key) {
    if (!root)
        return new Node(key);
    if (key < root->key)
        root->left = insert(root->left, key);
    else
        root->right = insert(root->right, key);
    return balance(root);
}

Node* findMin(Node* p) {
    return p->left ? findMin(p->left) : p;
}

Node* removeMin(Node* p) {
    if (p->left == nullptr)
        return p->right;
    p->left = removeMin(p->left);
    return balance(p);
}

Node* remove(Node* root, int key) {
    if (!root)
        return nullptr;
    if (key < root->key)
        root->left = remove(root->left, key);
    else if (key > root->key)
        root->right = remove(root->right, key);
    else {
        Node* l = root->left;
        Node* r = root->right;
        delete root;
        if (!r) return l;
        Node* min = findMin(r);
        min->right = removeMin(r);
        min->left = l;
        return balance(min);
    }
    return balance(root);
}

Node* search(Node* root, int key) {
    if (!root)
        return nullptr;
    if (root->key == key)
        return root;
    if (root->key > key)
        return search(root->left, key);
    else
        return search(root->right, key);
}

Node* next(Node* root, int key) {
    Node* res = nullptr;
    while (root) {
        if (root->key > key) {
            if (!res || res->key > root->key)
                res = root;
            root = root->left;
        }
        else
            root = root->right;
    }
    return res;
}

Node* prev(Node* root, int key) {
    Node* res = nullptr;
    while (root) {
        if (root->key < key) {
            if (!res || res->key < root->key)
                res = root;
            root = root->right;
        }
        else
            root = root->left;
    }
    return res;
}
参考文献