从零开始手写STL库:Map

从零开始手写STL库–Map的实现

Github链接:miniSTL



一、Map是什么

std::map是基于红黑树构建的数组结构,能够储存键和值这样的数据对,并且不允许重复元素的存在

在这里插入图片描述

二、Set要包含什么函数

基于本流程中实现过的红黑树,封装一层就可以了

不过这里额外实现一下std::map的访问方式,也就是atoperator[]的实现

正常的封装一下插入删除查找等函数:

template<typename Key, typename Value>
class myMap
{
private:
    myRedBlackTree<Key, Value> rbTree;

public:
    Map() : rbTree() {}
    ~Map() {}

    void insert(const Key &key, const Value &value) { rbTree.insert(key, value); }
    void erase(const Key &key) { rbTree.remove(key); }
    size_t size() { return rbTree.getSize(); }
    bool empty() const { return rbTree.empty(); }
    bool contains(const Key &key) { return rbTree.at(key) != nullptr; }
};

关于at的实现则调用红黑树的查找函数,如下:

    Value &at(const Key &key) 
    {
        Value *foundVal = rbTree.at(key);
        if (foundVal) 
        {
            return *foundVal;
        } 
        else 
        {
            throw std::out_of_range("Key not found");
        }
    }

同样的,operator[]的重构也调用at函数,如下:

    Value &operator[](const Key &key) 
    {
        Value *foundVal = rbTree.at(key);
        if (foundVal) return *foundVal; 
        else 
        {
            Value defaultValue;
            rbTree.insert(key, defaultValue);
            return *rbTree.at(key);
        }
    }

不同的在于,如果operator[]访问发现没有这个元素,会将该元素插入进树中

这里也是符合STL库的使用规范的,因为在STL库中,虽然at和[]都可以访问元素,但是原理是不同的

在vector中:
at()访问会做边界检查,如果越界会抛出异常,相对来说安全
operator[]不会,即便是越界也会返回一个引用,只是这个引用必然是错误的,基于该返回值做什么操作都有些危险

在map中:
operator[]会检查元素是否存在,如果不存在就插入该元素,并返回引用

所以这里的实现就将这一过程复现了,关于operator[]的知识点,在Effective STL的第二十四条中也有介绍:Effective STL

有关map的插入效率问题,可以串联起来看

总结

map的查找删除搜索效率一样,都是O(logn),这是由于它是由红黑树为底层构建的

还需要注意一个问题:如果std::map的键类型是自定义类型,需要怎么做?

答案是重载operator<或者定义比较函数,不过根据Effective STL的意见,更合适的方式是定义比较函数

不过两者均可,不考虑别的程序员可能误解代码的情况下,使用哪个方法都可以,如:

struct myCompare 
{
    bool operator()(const myKey& a, const myKey& b) const 
    {
        return a.key < b.key;
    }
};
std::map<myKey, int, myCompare> myMap;

或者:

struct myKey 
{
    int key;
    bool operator<(const myKey& other) const 
    {
        return key < other.key;
    }
};
std::map<myKey, int> myMap;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值