在 C++ 中,mapset 是非常常用的 STL(标准模板库)容器,它们在存储数据时提供了高效的查找、插入和删除操作。不过,了解它们的内部实现原理有助于我们更深入地掌握 C++。本文将通过模拟实现 mapset 的基本功能,给出代码示例并进行详细说明。

一、set 的实现

set 是一种不允许重复元素的集合,通常基于红黑树或其他自平衡二叉搜索树来实现。这里,我们用简单的二叉搜索树进行模拟实现。

#include <iostream>

template<typename T>
class Set {
private:
    struct Node {
        T data;
        Node *left, *right;

        Node(T value) : data(value), left(nullptr), right(nullptr) {}
    };

    Node *root;

    void insert(Node *&node, T value) {
        if (node == nullptr) {
            node = new Node(value);
            return;
        }
        if (value < node->data) {
            insert(node->left, value);
        } else if (value > node->data) {
            insert(node->right, value);
        }
        // 如果 value == node->data,则不插入,保持集合的唯一性
    }

    void inorder(Node *node) {
        if (node) {
            inorder(node->left);
            std::cout << node->data << " ";
            inorder(node->right);
        }
    }

public:
    Set() : root(nullptr) {}

    void insert(T value) {
        insert(root, value);
    }

    void display() {
        inorder(root);
        std::cout << std::endl;
    }
};

在以上代码中,我们定义了一个简单的 Set 类,包含了插入元素和中序遍历(用于显示元素顺序)的方法。关键在于 insert 方法的逻辑,确保不插入重复的元素。

二、map 的实现

map 是一对键值对的集合,允许通过键高效地查找对应的值。我们同样可以用二叉搜索树来模拟实现。每个节点存储一个键值对。

#include <iostream>
#include <utility>

template<typename K, typename V>
class Map {
private:
    struct Node {
        K key;
        V value;
        Node *left, *right;

        Node(K k, V v) : key(k), value(v), left(nullptr), right(nullptr) {}
    };

    Node *root;

    void insert(Node *&node, K key, V value) {
        if (node == nullptr) {
            node = new Node(key, value);
            return;
        }
        if (key < node->key) {
            insert(node->left, key, value);
        } else if (key > node->key) {
            insert(node->right, key, value);
        } else {
            // 如果 key 已存在,更新值
            node->value = value;
        }
    }

    V* find(Node *node, K key) {
        if (node == nullptr) return nullptr;
        if (key < node->key) {
            return find(node->left, key);
        } else if (key > node->key) {
            return find(node->right, key);
        } else {
            return &node->value; // 找到了,返回值的地址
        }
    }

public:
    Map() : root(nullptr) {}

    void insert(K key, V value) {
        insert(root, key, value);
    }

    V* find(K key) {
        return find(root, key);
    }
};

Map 类中,插入元素时会根据键的大小关系将数据放置在树的相应位置。同样,我们实现了一个 find 方法来查找键对应的值。

使用示例

int main() {
    Set<int> mySet;
    mySet.insert(5);
    mySet.insert(3);
    mySet.insert(8);
    mySet.insert(5); // 重复插入,不会生效

    std::cout << "Set contains: ";
    mySet.display(); // 应该输出: 3 5 8

    Map<std::string, int> myMap;
    myMap.insert("apple", 1);
    myMap.insert("banana", 2);
    myMap.insert("orange", 3);
    myMap.insert("apple", 4); // 更新值

    std::string key = "apple";
    int *value = myMap.find(key);
    if (value) {
        std::cout << key << ": " << *value << std::endl; // 输出: apple: 4
    } else {
        std::cout << key << " not found." << std::endl;
    }

    return 0;
}

总结

以上是对 C++ 中 setmap 的基本模拟实现。虽然代码相对简单,功能也未必完整,但这提供了对其内部机制的基本认识。真实的 STL 实现会更加复杂,涉及内存管理、迭代器、异常处理等,深入研究可以帮助我们写出更高效和安全的代码。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部