C++ 笔记(24)— STL map 类(map实例化、插入、查找、删除)

1. STL 映射类简介

mapmultimap 是键-值对容器,支持根据键进行查找,区别在于,后者能够存储重复的键,而前者只能存储唯一的键。

为了实现快速查找, STL mapmultimap 的内部结构看起来像棵二叉树。这意味着在 mapmultimap 中插入元素时将进行排序;还意味着不像 vector 那样可以使用其他元素替换给定位置的元素,位于 map 中特定位置的元素不能替换为值不同的新元素,这是因为 map 将把新元素同二叉树中的其他元素进行比较,进而将它放在其他位置。

要使用 STL mapmultimap 类,需要包含头文件 <map>

#include <map>

2. STL map 和 multimap 的基本操作

STL mapmultimap 都是模板类,要使用其成员函数,必须先实例化。

2.1 实例化 std::map 和 std::multimap

要实例化将整数用作键、将字符串用作值的 mapmultimap ,必须具体化模板类 std::mapstd::multimap

实例化模板类 map 时,需要指定键和值的类型以及可选的谓词(它帮助 map 类对插入的元素进行排序)。因此,典型的 map 实例化语法如下:

#include <map>
using namespace std;
...
map <keyType, valueType, Predicate=std::less <keyType>> mapObj;
multimap <keyType, valueType, Predicate=std::less <keyType>> mmapObj;

第三个模板参数是可选的。如果您值指定了键和值的类型,而省略了第三个模板参数, std::mapstd::multimap 将把 std::less<> 用作排序标准,这将元素按升序排列。因此,将整数映射到字符串的 mapmultimap 类似于下面这样:

std::map<int, string> mapIntToStr;
std::multimap<int, string> mmapIntToStr;

实例化示例:

int main ()
{
    using namespace std;
    // map and multimap key of type int to value of type string
    map<int, string> a;
    multimap<int, string> ma;

    // map and multimap constructed as a copy of another
    map<int, string> b(a);
    multimap<int, string> mb(ma);

    // map and multimap constructed given a part of another map or multimap
    map<int, string> c(a.cbegin(), a.cend());

    multimap<int, string> mc(ma.cbegin(),ma.cend());

    return 0;
}

2.2 在 STL map 或 multimap 中插入元素

mapmultimap 的大多数函数的用法类似,它们接受类似的参数,返回类型也类似。例如,要在这两种容器中插入元素,都可使用成员函数 insert

using namespace std;
map<int, string> d;
// insert pair of key and value using make_pair function
d.insert (make_pair (-1, "Minus One"));

鉴于这两种容器包含的元素都是键-值对,因此也可直接使用 std::pair 来指定要插入的键和值:

d.insert (pair <int, string>(1000, "One Thousand"));

另外,还可使用类似于数组的语法进行插入。是由下标运算符 [] 支持的:

d[1000000] = "One Million";

还可使用 map 来实例化 multimap

multimap<int, std::string> md(d.cbegin(), d.cend());

插入代码示例:

#include <map>
#include <iostream>
#include <string>

using namespace std;

// 使用 typedef 指定别名,方便阅读
typedef map<int, string> MAP_INT_STRING;
typedef multimap<int, string> MMAP_INT_STRING;

// 使用迭代器来访问表示键的 first 以及表示值的second
template <typename T>
void DisplayContents (const T& cont)
{
    for (auto element = cont.cbegin(); element != cont.cend(); ++ element)
    {
        cout << element->first << " -> " << element->second << endl;
    }
    
    cout << endl;
}

 int main ()
 {
    MAP_INT_STRING mapIntToStr;

    // 使用 value_type 插入键值对
    mapIntToStr.insert(MAP_INT_STRING::value_type (3, "Three"));

    // 使用 make_pair 函数插入键值对
    mapIntToStr.insert(make_pair (-1, "Minus One"));

    // 直接使用 pair 对象插入函数
    mapIntToStr.insert(pair<int, string>(1000, "One Thousand"));

    // 使用数组方式插入键值对
    mapIntToStr[1000000] = "One Million";

    cout << "The map contains " << mapIntToStr.size ();
    cout << " key-value pairs. They are: " << endl;
    DisplayContents(mapIntToStr);

    // instantiate a multimap that is a copy of a map
    MMAP_INT_STRING mmapIntToStr(mapIntToStr.cbegin(), mapIntToStr.cend());

    // The insert function works the same way for multimap too
    // A multimap can store duplicates - insert a duplicate
    mmapIntToStr.insert (make_pair (1000, "Thousand"));

    cout << endl << "The multimap contains " << mmapIntToStr.size();
    cout << " key-value pairs. They are: " << endl;
    cout << "The elements in the multimap are: " << endl;
    DisplayContents(mmapIntToStr);

    // The multimap can return number of pairs with same key
    cout << "The number of pairs in the multimap with 1000 as their key: "
    << mmapIntToStr.count (1000) << endl;

    return 0;
}

2.3 在 STL map 中查找元素

诸如 mapmultimap 等关联容器都提供了成员函数 find() ,它让您能够根据给定的键查找值。 find() 总是返回一个迭代器:

multimap <int, string>::const_iterator pairFound = mapIntToStr.find(key);

如果使用的编译器遵循 C++11 标准,可使用关键字 auto 来简化迭代器声明:

auto pairFound = mapIntToStr.find(key);

编译器将根据 map::find() 的返回类型自动推断出迭代器的类型。

应首先检查该迭代器,确保 find() 已成功,再使用它来访问找到的值:

if (pairFound != mapIntToStr.end())
{
    cout << "Key " << pairFound->first << " points to Value: ";
    cout << pairFound->second << endl;
}
else
	cout << "Sorry, pair with key " << key << " not in map" << endl;

完整示例代码如下:

#include <map>
#include <iostream>
#include <string>

using namespace std;

// 使用迭代器来访问表示键的 first 以及表示值的second
template <typename T>
void DisplayContents (const T& cont)
{
    for (auto element = cont.cbegin(); element != cont.cend(); ++ element)
    {
        cout << element->first << " -> " << element->second << endl;
    }
    
    cout << endl;
}

 int main ()
 {
    map<string, string> d;
    d["a"] = "1";
    d.insert(make_pair("b", "2"));
    d.insert(make_pair("c", "3"));

    DisplayContents(d);

    string key = "c";
    auto pairFound = d.find(key);
    if (pairFound != d.end())
    {
        cout << "Key " << pairFound->first << " points to Value: ";
        cout << pairFound->second << endl;
    }
    else
        cout << "Sorry, pair with key " << key << " not in map" << endl;
        return 0;
}

2.4 在 STL multimap 中查找元素

如果 2.3 小节程序使用的是 multimap ,容器可能包含多个键相同的键-值对,因此需要找到与指定键对应的所有值。为此,可使用 multimap::count() 确定有多少个值与指定的键对应,再对迭代器递增,以访问这些相邻的值:

auto pairFound = mmapIntToStr.find(key);
// Check if find() succeeded
if(pairFound != mmapIntToStr.end())
{
    // Find the number of pairs that have the same supplied key
    size_t numPairsInMap = mmapIntToStr.count(1000);
    for(size_t counter = 0; counter < numPairsInMap; ++ counter )
    {
        cout << "Key: " << pairFound->first; // key
        cout << ", Value [" << counter << "] = ";
        cout << pairFound->second << endl; // value
        ++ pairFound;
    }
}
else
	cout << "Element not found in the multimap";

2.5 删除 STL map 或 multimap 中的元素

mapmultimap 提供了成员函数 erase() ,该函数删除容器中的元素。调用 erase 函数时将键作为参数,这将删除包含指定键的所有键-值对:

mapObject.erase(key);

函数 erase() 的另一种版本接受迭代器作为参数,并删除迭代器指向的元素:

mapObject.erase(element);

还可使用迭代器指定边界,从而将指定范围内的所有元素都从 mapmultimap 中删除:

mapObject.erase(lowerBound, upperBound);

完整示例代码:

#include <map>
#include <string>
#include <iostream>

using namespace std;

template<typename T>
void DisplayContents(const T& cont)
{
    for (auto element = cont.cbegin(); element != cont.cend(); ++ element)
        cout<< element->first<< " -> "<< element->second<< endl;

    cout<< endl;
}

int main()
{
    multimap<int, string> mmapIntToStr;

    // Insert key-value pairs into the multimap
    mmapIntToStr.insert(make_pair(3, "Three"));
    mmapIntToStr.insert(make_pair(45, "Forty Five"));
    mmapIntToStr.insert(make_pair(-1, "Minus One"));
    mmapIntToStr.insert(make_pair(1000, "Thousand"));

    // Insert duplicates into the multimap
    mmapIntToStr.insert(make_pair(-1, "Minus One"));
    mmapIntToStr.insert(make_pair(1000, "Thousand"));

    cout<< "The multimap contains "<< mmapIntToStr.size();
    cout<< " key-value pairs. "<< "They are: "<< endl;
    DisplayContents(mmapIntToStr);

    // Erasing an element with key as -1 from the multimap
    auto numPairsErased = mmapIntToStr.erase(-1);
    cout<< "Erased " << numPairsErased << " pairs with -1 as key."<< endl;

    // Erase an element given an iterator from the multimap
    auto pair = mmapIntToStr.find(45);
    if(pair != mmapIntToStr.end())
    {
        mmapIntToStr.erase(pair);
        cout<< "Erased a pair with 45 as key using an iterator"<< endl;
    }

    // Erase a range from the multimap...
    cout << "Erasing the range of pairs with 1000 as key." << endl;
    mmapIntToStr.erase(mmapIntToStr.lower_bound(1000), mmapIntToStr.upper_bound(1000) );

    cout<< "The multimap now contains "<< mmapIntToStr.size();
    cout<< " key-value pair(s)."<< "They are: "<< endl;
    DisplayContents(mmapIntToStr);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wohu007

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

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

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

打赏作者

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

抵扣说明:

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

余额充值