C++容器之映射(std::map)

1 概述

  映射是关联容器,存储由键值和映射值的组合组成的元素,遵循特定的顺序。

  在映射中,键值通常用于对元素进行排序和唯一标识,而映射的值存储与该键关联的内容。键和映射值的类型可能不同,并在成员类型value_type中分组在一起,该类型是将两者组合在一起的对类型:
  typedef pair<const Key,T> value_type;

  在内部,映射中的元素总是按照其键进行排序,遵循由其内部比较对象(类型为Compare)指示的特定严格弱排序标准。

  map容器通过关键字访问单个元素的速度通常unordered_map容器慢,但它们允许根据子集的顺序直接迭代。

  映射中的映射值可以通过使用括号运算符(operator[])的相应键直接访问。

  映射通常被实现为二叉搜索树
其类图如下:
类图

2 使用实例

void MapSuite::find()
{
   std::map<char, int> a = { {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
   auto it =  a.find('e');
   TEST_ASSERT_EQUALS('e', it->first)
   TEST_ASSERT_EQUALS(50, it->second)
   it =  a.find('h');
   TEST_ASSERT_EQUALS(true, it == a.end())
}

void MapSuite::count()
{
   std::map<char, int> a = { {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
   TEST_ASSERT_EQUALS(1, a.count('e'))
   TEST_ASSERT_EQUALS(0, a.count('h'))
}

3 接口使用

3.1 construct

namespace helper_of_map {
bool function_compare(char l, char r) { return l < r; }
struct object_compare
{
    bool operator()(const char& l, const char& r) { return l < r; }
};
}

void MapSuite::construct()
{
    std::map<char, int> a;
    std::map<char, int> b = { { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50}};
    std::map<char, int> c(b.begin(), b.end());
    std::map<char, int> d(b);
    std::map<char, int> e({ { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 } , { 'a', 10 } });
    std::map<char, int, helper_of_map::object_compare> f;
    std::map<char, int, bool(*)(char, char)> g(helper_of_map::function_compare);

    TEST_ASSERT_EQUALS(true, a.empty())
    TEST_ASSERT_EQUALS(5, b.size())
    TEST_ASSERT_EQUALS(5, c.size())
    TEST_ASSERT_EQUALS(5, d.size())
    TEST_ASSERT_EQUALS(5, e.size())
    TEST_ASSERT_EQUALS(true, f.empty())
    TEST_ASSERT_EQUALS(true, g.empty())
}

说明:

  • 构造时可以指定函数对象作为比较函数
  • 构造时可以指定函数指针作为比较函数

3.2 assigns

void MapSuite::assigns()
{
    std::map<char, int> a = { { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 }, { 'e', 60 } };
    std::map<char, int> b;
    std::map<char, int> c;
    std::map<char, int> d;
    b = a;
    c = { { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 }, { 'a', 10 } };
    d = std::map<char, int>({ { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 } });
    TEST_ASSERT_EQUALS(5, a.size())
    TEST_ASSERT_EQUALS(5, b.size())
    TEST_ASSERT_EQUALS(5, c.size())
    TEST_ASSERT_EQUALS(5, d.size())
}

3.3 iterators

void MapSuite::iterators()
{
    std::map<char, int> a = { {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }};
    char keys[]  =  { 'a', 'b' , 'c', 'd', 'e' };
    char rkeys[] =  { 'e', 'd' , 'c', 'b', 'a' };
    int values[]  = { 10, 20, 30, 40, 50 };
    int rvalues[] = { 50, 40, 30, 20, 10 };

    int index = 0;
    for(auto it = a.begin(); it != a.end(); ++it)
    {
        TEST_ASSERT_EQUALS(keys[index], it->first)
        TEST_ASSERT_EQUALS(values[index++], it->second)
    }
    
    index = 0;
    for(auto it = a.cbegin(); it != a.cend(); ++it)
    {
        TEST_ASSERT_EQUALS(keys[index], it->first)
        TEST_ASSERT_EQUALS(values[index++], it->second)
    }

    index = 0;
    for(auto it = a.rbegin(); it != a.rend(); ++it)
    {
        TEST_ASSERT_EQUALS(rkeys[index], it->first)
        TEST_ASSERT_EQUALS(rvalues[index++], it->second)
    }
    
    index = 0;
    for(auto it = a.crbegin(); it != a.crend(); ++it)
    {
        TEST_ASSERT_EQUALS(rkeys[index], it->first)
        TEST_ASSERT_EQUALS(rvalues[index++], it->second)
    }
}

3.4 capacity

void MapSuite::capacity()
{
    std::map<char, int> a;
    std::map<char, int> b = { {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
    TEST_ASSERT_EQUALS(true, a.empty())
    TEST_ASSERT_EQUALS(0, a.size())
    TEST_ASSERT_EQUALS(5, b.size())
    TEST_ASSERT_EQUALS(b.max_size(), a.max_size())
}

3.5 access

void MapSuite::access()
{
    std::map<char, int> a;
    std::map<char, int> b = { { 'a', 10 }, { 'b', 20 }};
    bool hasExcpetion = false;
    a['a'] = 10;
    a['b'] = 20;

    b.at('a') = 20;
    b.at('b') = 30;

    try
    {
        b.at('c') = 40;
    }
    catch(...)
    {
        hasExcpetion = true;
    }
    TEST_ASSERT_EQUALS(10, a['a'])
    TEST_ASSERT_EQUALS(20, a['b'])
    TEST_ASSERT_EQUALS(20, b['a'])
    TEST_ASSERT_EQUALS(30, b['b'])
    TEST_ASSERT_EQUALS(true, hasExcpetion)
}

说明:

  • []函数如果map中没有对应key则添加,value是对应类型的默认值
  • at函数如果map中没有对应key则抛异常

3.6 insert

void MapSuite::insert()
{
    std::map<char, int> a = { {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
    std::map<char, int> b;
    std::map<char, int> c;
    std::map<char, int>::iterator it;
    std::pair<std::map<char, int>::iterator,bool> r = a.insert({ 'b', 20 });//{ 'b', 20 } no inserted
    if(r.second == false)
    {
        it = r.first;
        TEST_ASSERT_EQUALS('b', it->first)//*it =  { 'b', 20 } 
    }
    a.insert(it, {'f', 60 });
    it = a.insert(it, {'g', 70 });
    TEST_ASSERT_EQUALS('g', it->first)
    it = a.insert(it, {'f', 60 }); //no inserted
    TEST_ASSERT_EQUALS('f', it->first)

    b.insert(a.begin(), a.end());
    c.insert({ {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } });
    int array[] = { 10, 20, 30, 40, 50, 60, 70 };
    int index = 0;
    for(auto it = a.begin(); it != a.end(); ++it)
        TEST_ASSERT_EQUALS(array[index++], it->second)

    index = 0;
    for(auto it = b.begin(); it != b.end(); ++it)
        TEST_ASSERT_EQUALS(array[index++], it->second)
    
    index = 0;
    for(auto it = c.begin(); it != c.end(); ++it)
        TEST_ASSERT_EQUALS(array[index++], it->second)
}

说明:

  • 不带位置参数插入函数,返回std::pair对象,pair::first指新加入元素或集合中已存在元素,pair::second为true说明插入成功,为false说明集合中已有该元素
  • 带位置参数插入函数,返回iterator,指向新加入元素或集合中已存在元素。

3.7 erase

void MapSuite::erase()
{
    std::map<char, int> a = { {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
    auto it = a.erase(a.begin()); // { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 }
    TEST_ASSERT_EQUALS('b', it->first)
    TEST_ASSERT_EQUALS(1, a.erase('c'))// { 'b', 20 }, { 'd', 40 }, {'e', 50 }
    TEST_ASSERT_EQUALS(0, a.erase('c'))
    it = a.begin();
    ++it;
    TEST_ASSERT_EQUALS('d', it->first)
    it = a.erase(it, a.end());  // { 'b', 20 }
    TEST_ASSERT_EQUALS(1, a.size())
}

说明:

  • 按值删除返回删除元素个数
  • 按位置删除返回iterator指向被删除元素的下一位置

3.8 swap

void MapSuite::swap()
{
    std::map<char, int> a;
    std::map<char, int> b = { { 'a', 10 }, { 'b', 20 }};

    TEST_ASSERT_EQUALS(true, a.empty())
    TEST_ASSERT_EQUALS(2, b.size())
    a.swap(b);
    TEST_ASSERT_EQUALS(2, a.size())
    TEST_ASSERT_EQUALS(true, b.empty())
}

3.9 clear

void MapSuite::clear()
{
    std::map<char, int> a = { { 'a', 10 }, { 'b', 20 }};

    TEST_ASSERT_EQUALS(2, a.size())
    a.clear();
    TEST_ASSERT_EQUALS(true, a.empty())
}

3.10 emplace

void MapSuite::emplace()
{
    std::map<char, int> a;
    a.emplace('a', 10);
    a.emplace('b', 20);
    TEST_ASSERT_EQUALS(2, a.size())
    auto r = a.emplace('a', 10);
    TEST_ASSERT_EQUALS('a', r.first->first)
    TEST_ASSERT_EQUALS(false, r.second)
    TEST_ASSERT_EQUALS(2, a.size())
}
  • 返回值为std::pair对象,pair::first指新加入元素或集合中已存在元素,pair::second为true说明插入成功,为false说明集合中已有该元素

3.11 emplace_hint

void MapSuite::emplace_hint()
{
    std::map<char, int> a = { { 'a', 10 }, { 'b', 20 } };
    auto it = a.emplace_hint(a.begin(), 'c',  30);
    TEST_ASSERT_EQUALS('c', it->first);
    it = a.emplace_hint(it, 'b',  20);
    TEST_ASSERT_EQUALS('b', it->first)
}

说明:

  • 返回值为iterator对象,指向新加入元素或集合中已存在元素。

3.12 key_comp

void MapSuite::key_comp()
{
    std::map<char, int> a = { {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
    std::map<char, int> b;
    std::map<char, int>::key_compare compare = a.key_comp();
    
    char hightest = a.rbegin()->first;
    for(auto  it = a.begin(); it != a.end(); ++it)
    {
        if(compare(it->first, hightest))
            b.insert(*it);
    }

    int index = 0;
    char array [] = { 'a', 'b', 'c', 'd', 'e' };
    for(auto i : b)
    {
        TEST_ASSERT_EQUALS(array[index++], i.first)
    }
    TEST_ASSERT_EQUALS(4, b.size())
}

说明:

  • 对map来说,key_comp的参数类型是key的类型这里是char

3.13 value_comp

void MapSuite::value_comp()
{
    std::map<char, int> a = { {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
    std::map<char, int> b;
    std::map<char, int>::value_compare compare = a.value_comp();
    
    auto hightest = *a.rbegin();
    for(auto  it = a.begin(); it != a.end(); ++it)
    {
        if(compare(*it, hightest))
            b.insert(*it);
    }

    int index = 0;
    int array [] = { 10, 20, 30, 40, 50 };
    for(auto i : b)
    {
        TEST_ASSERT_EQUALS(array[index++], i.second)
    }
    TEST_ASSERT_EQUALS(4, b.size())
}
  • 对map来说,value_comp的参数是类型是std::pair<char, int>而不是int

3.14 find/count

void MapSuite::find()
{
    std::map<char, int> a = { {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
    auto it =  a.find('e');
    TEST_ASSERT_EQUALS('e', it->first)
    TEST_ASSERT_EQUALS(50, it->second)
    it =  a.find('h');
    TEST_ASSERT_EQUALS(true, it == a.end())
}

void MapSuite::count()
{
    std::map<char, int> a = { {'e', 50 },  { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
    TEST_ASSERT_EQUALS(1, a.count('e'))
    TEST_ASSERT_EQUALS(0, a.count('h'))
}

3.15 upper_bound/upper_bound/equal_range

void MapSuite::lower_bound()
{
    std::map<char, int> a = { { 'a', 10 },  { 'c', 30 }, { 'd', 40 }, {'e', 50 } };
    auto it =  a.lower_bound('b');//>=b
    TEST_ASSERT_EQUALS('c', it->first)

    it =  a.lower_bound('d');//>=d
    TEST_ASSERT_EQUALS('d', it->first)

    it =  a.lower_bound('f');
    TEST_ASSERT_EQUALS(true, it == a.end())
}
void MapSuite::upper_bound()
{
    std::map<char, int> a = { { 'a', 10 },  { 'c', 30 }, { 'd', 40 }, {'e', 50 } };
    auto it =  a.upper_bound('c'); // > c
    TEST_ASSERT_EQUALS('d', it->first)

    it =  a.upper_bound('f');// > f
    TEST_ASSERT_EQUALS(true, it == a.end())
}
void MapSuite::equal_range()
{
    std::map<char, int> a = { { 'a', 10 },  { 'c', 30 }, { 'd', 40 }, {'e', 50 } };
    auto it =  a.equal_range('c'); // >=c & > c
    TEST_ASSERT_EQUALS('c', it.first->first)
    TEST_ASSERT_EQUALS('d', it.second->first)

    it =  a.equal_range('b'); // >= b & > b
    TEST_ASSERT_EQUALS('c', it.first->first)
    TEST_ASSERT_EQUALS('c', it.second->first)
}

说明:

  • lower_bound 返回第一个大于等(>=)于指定值的iterator
  • upper_bound 返回第一个大于(>)指定值的iterator
  • equal_range 返回std::pair对象, pair::first是第一个大于等(>=)于指定值的iterator,pair::second是第一个大于(>)指定值的iterator

3.16 get_allocator

void MapSuite::get_allocator()
{
    std::map<char,int> a;
    auto allocator = a.get_allocator();
    std::pair<const char,int>* p = allocator.allocate(5);

    allocator.deallocate(p, 5);
        try
    {
        p = allocator.allocate(allocator.max_size() + 1);
    }
    catch(...)
    {
        p = nullptr;
    }
    TEST_ASSERT_EQUALS(true, p == nullptr)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flysnow010

你的鼓励就是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值