📜  unordered_multimap及其应用(1)

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

unordered_multimap及其应用

1. 什么是unordered_multimap?

unordered_multimap是C++ STL中的一个关联容器,它将一组键和一组值配对存储。和std::map类似,但它允许多个元素具有相同的键。特别地,这些键值对没有固定的顺序,底层实现为哈希表,对于键的顺序没有要求。

2. unordered_multimap的用途

一般用于需要快速(O(1))查找、插入和删除元素的场景。

可以用于统计单词出现的次数,将行号与每个单词对应起来,统计访问日志中IP的数量等等。

3. 如何使用unordered_multimap?

首先应该#include <unordered_multimap>头文件。

3.1. 声明方式:
std::unordered_multimap<int, std::string> umap;

这样就声明了一个空的unordered_multimap对象umap,其中键为int类型,值为std::string类型。

3.2. 插入元素:
umap.insert({1, "apple"});
umap.insert({2, "banana"});
umap.insert({3, "orange"});

插入方式和其他STL容器非常类似,使用insert()函数。

如果你想插入一组键值对,在C++11之前必须这样做:

std::pair<int, std::string> p(4, "watermelon");
umap.insert(p);

而在C++11及以后,你可以这样插入:

umap.insert(std::make_pair(4, "watermelon"));

还可以使用emplace()函数,它在插入元素时不需要使用std::pair模板。

umap.emplace(5, "pear");
3.3. 查找元素:

unordered_multimap在查找元素时需要注意的是,由于内部实现为哈希表,它没有固定的数值顺序,即使你在插入时是按照顺序来的。

std::unordered_multimap<int, std::string>::iterator itr;  // 迭代器
itr = umap.find(2);  // 查找键为2的元素
if (itr != umap.end()) {
    std::cout << "找到了,值为:" << itr->second << std::endl;
} else {
    std::cout << "没找到" << std::endl;
}

在上述代码中, umap.find(2) 会返回一个指向键为2的元素的迭代器。如果找到了,则输出该元素的值,否则输出 "没找到"。

如果你想遍历整个unordered_multimap,可以使用迭代器:

for (auto itr = umap.begin(); itr != umap.end(); ++itr) {
    std::cout << itr->first << ": " << itr->second << std:endl;
}

也可以用auto关键字:

for (auto& e : umap) {
    std::cout << e.first << ": " << e.second << std::endl;
}
3.4. 删除元素:

和其他STL容器一样,unordered_multimap也可以使用erase()函数删除元素。

umap.erase(2);  // 删除键为2的元素
umap.erase(umap.begin());  // 删除第一个元素
umap.erase(umap.find(1), umap.end());  // 删除键为1的所有元素
3.5. 案例
#include <iostream>
#include <unordered_multimap>
#include <string>

int main() {
    std::unordered_multimap<std::string, int> umap;

    // 添加元素
    umap.emplace("apple", 10);
    umap.emplace("orange", 20);
    umap.emplace("banana", 15);
    umap.emplace("kiwi", 5);
    umap.emplace("apple", 18);
    umap.emplace("orange", 30);

    // 查找元素
    std::cout << "apple的值为:";
    auto range = umap.equal_range("apple");
    for (auto itr = range.first; itr != range.second; ++itr) {
        std::cout << itr->second << " ";
    }

    std::cout << std::endl;

    // 遍历
    for (auto& e : umap) {
        std::cout << e.first << ": " << e.second << std::endl;
    }

    // 删除元素
    umap.erase("kiwi");

    // 遍历
    for (auto& e : umap) {
        std::cout << e.first << ": " << e.second << std::endl;
    }

    return 0;
}

输出:

apple的值为:10 18 
orange: 20
orange: 30
kiwi: 5
banana: 15
apple: 10
apple: 18
banana: 15
orange: 20
orange: 30
apple: 10
apple: 18
orange: 20
orange: 30
banana: 15
kiwi: 5
orange: 20
orange: 30
banana: 15
apple: 10
apple: 18
orange: 20
orange: 30
banana: 15
4. unordered_multimap与其他STL容器的比较

和其他关联容器(如map、multimap等),unordered_multimap的特点是允许多个元素具有相同的键。和vector、deque、list、forward_list等其他STL容器不同的是,unordered_multimap不是线性容器,而是哈希容器。因此,它的性能特点也不同,无法在数组或链表上保证O(1)的操作。unordered_multimap的查找、插入和删除操作的复杂度都是O(1),而其他容器的复杂度则是O(logN)。

unordered_multimap一般比其他STL关联容器速度更快,因为它使用哈希表来实现。但是,它的不同点也带来了一些问题,如它的元素没有固定的顺序;哈希容器不是线性容器,所以迭代器的增加不一定是连续的;哈希表会浪费一些空间用于存储散列表,所以unordered_multimap的内存占用比其他STL关联容器稍大。

5. 总结

unordered_multimap是STL中一种基于哈希表实现的关联容器,允许多个元素具有相同的键。它适用于需要快速查找、插入和删除元素的场景,如统计单词出现的次数、将行号与每个单词对应起来、统计访问日志中IP的数量等等。unordered_multimap与其他STL容器相比,具有更快的速度和更低的复杂度。但它也有一些缺点,如元素没有固定的顺序、迭代器的增加不一定是连续的、内存占用比其他STL关联容器稍大等。

参考资料:

官方文档:https://en.cppreference.com/w/cpp/container/unordered_multimap