C++ STL unordered_map/multimap使用

C++ unordered_map/multimap使用

概述

  • unordered_map 与 unordered_multimap 都定义于头文件<unordered_map>
  • unordered_map 是关联容器,含有带唯一键的键-值 pair 。搜索、插入和元素移除拥有平均常数时间复杂度。
  • unordered_multimap 可以含有不唯一的 Key 。
  • unordered_map 与 unordered_multimap 成员函数及非成员函数使用方法相同,只是在 insert 函数内部,unordered_map 调用 insert_unique 函数不允许键重复,而 unordered_multimap 调用 insert_equal 函数允许键重复。
  • 在内部,元素并不以任何特别顺序排序,而是组织进桶中。元素被放进哪个桶完全依赖其值的哈希。这允许对单独元素的快速访问,因为哈希一旦确定,就准确指代元素被放入的桶。

类模板:

template<
    class Key,
    class T,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map;

创建unordered_map

构造函数

 	// 默认构造函数:空 unordered_map
    std::unordered_map<std::string, std::string> m1;
 
    // 列表构造函数
    std::unordered_map<int, std::string> m2 =
    {
        {1, "foo"},
        {3, "bar"},
        {2, "baz"},
    };
 
    // 复制构造函数
    std::unordered_map<int, std::string> m3 = m2;
 
    // 移动构造函数
    std::unordered_map<int, std::string> m4 = std::move(m2);
 
    // 范围构造函数
    std::vector<std::pair<std::bitset<8>, int>> v = { {0x12, 1}, {0x01,-1} };
    std::unordered_map<std::bitset<8>, double> m5(v.begin(), v.end());

opertor=

  • 赋值给容器
    定义:
// 复制赋值运算符。
unordered_map& operator=( const unordered_map& other );	

// 移动赋值运算符
unordered_map& operator=( unordered_map&& other );	

// 以 initializer_unordered_map iunordered_map 所标识者替换内容
unordered_map& operator=( std::initializer_unordered_map<T> iunordered_map ); 

用法:

    std::unordered_map<int> nums1 {3, 1, 4, 6, 5, 9};
    std::unordered_map<int> nums2;
    std::unordered_map<int> nums3;

    // 从 nums1 复制赋值数据到 nums2
    nums2 = nums1;
    // 从 nums1 移动赋值数据到 nums3,
    nums3 = std::move(nums1);
    // initializer_unordered_map 的复制赋值复制数据给 nums1
    nums1 = {1, 2, 3};

迭代器

begin\cbegin

在这里插入图片描述

  • 返回指向 unordered_map 首元素的迭代器。
  • cbegin中的c表示const,即返回const_iterator,不允许通过迭代器修改元素。
  • 若 unordered_map 为空,则返回的迭代器将等于 end() 。

定义:

iterator begin();
const_iterator cbegin() const noexcept;

end\cend

  • 返回指向 unordered_map 末元素后一元素的迭代器。

定义:

iterator end();
const_iterator cend() const noexcept;

容量

empty

  • 检查容器是否无元素,即是否 begin() == end() 。

定义:

bool empty() const;

用法:

	std::unordered_map<int, int> v;
	bool flag = v.empty();	// 输出 true

size

  • 返回容纳的元素数。 即 std::distance(begin(), end()) 。

定义:

size_type size() const;

用法:

	std::unordered_map<int, int> nums {1, 3, 5, 7};
    std::cout << nums.size() << std::endl;	// 输出 4

max_size

  • 返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end()) 。

定义:

size_type max_size() const;

用法:

	std::unordered_map<int, int> vi;
	std::cout << vi.max_size() << std::endl;	// 可能输出 4611686018427387903
	std::unordered_map<char, char> vc;
	std::cout << vc.max_size() << std::endl;	// 可能输出 18446744073709551615

修改器

clear

  • 从容器擦除所有元素。此调用后 size() 返回零。
  • 非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器亦被非法化。

定义:

void clear();

用法:

	std::unordered_map<int, char> container{{1, 'x'}, {2, 'y'}, {3, 'z'}};
	container.clear();
	std::cout << container.size() << std::endl;		// 输出 0

insert

  • 插入元素或结点

定义:

std::pair<iterator,bool> insert( const value_type& value );

std::pair<iterator,bool> insert( value_type&& value );

template< class InputIt >
void insert( InputIt first, InputIt last );

void insert( std::initializer_list<value_type> ilist );

用法:

    std::unordered_map<int, char> a;
 	
 	a.insert({4, 'c'});

	std::unordered_map<int, char> b {{1, 'x'}, {2, 'y'}, {3, 'z'}};
	a.insert(b.begin(), b.end());
	
 	a.insert({6, 'x'}, {7, 'y'});

insert_or_assign

  • 若等价于 k 的键已存在于容器中,则赋值 std::forward(obj) 给对应于键 k 的 mapped_type 。若键不存在,则如同用 insert 插入从 value_type(k, std::forward(obj)) 构造的新值。
	std::unordered_map<int, char> a{ {1, 'a'}, {2, 'b'} };
	a.insert({ 3, 'c' });
	a.insert_or_assign(1, 'd');		// a 中 1 对应 'd'

emplace

  原位构造元素
定义:

template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );;
	std::unordered_map<std::string, std::string> m;
 
    // 使用 pair 的移动构造函数
    m.emplace(std::make_pair(std::string("a"), std::string("a")));
 
    // 使用 pair 的转换移动构造函数
    m.emplace(std::make_pair("b", "abcd"));
 
    // 使用 pair 的模板构造函数
    m.emplace("d", "ddd");
 
    // 使用 pair 的逐片构造函数
    m.emplace(std::piecewise_construct,
              std::forward_as_tuple("c"),
              std::forward_as_tuple(10, 'c'));
    // C++17 起,能使用 m.try_emplace("c", 10, 'c');

emplace_hint

  • 使用提示原位构造元素
  • 返回值
      返回指向新插入元素的迭代器。

定义:

template <class... Args>
iterator emplace_hint( const_iterator hint, Args&&... args );

erase

  • 从容器擦除指定的元素。

定义:

// 1、移除位于 pos 的元素。
iterator erase( iterator pos );

// 2、移除范围 [first; last) 中的元素。
iterator erase( iterator first, iterator last );

// 3、移除关键等于 key 的元素(若存在一个)。
size_type erase( const key_type& key )

用法:

#include <unordered_map>
#include <iostream>
int main()
{
    std::unordered_map<int, std::string> c = {{1, "one"}, {2, "two"}, {3, "three"},
                                    {4, "four"}, {5, "five"}, {6, "six"}};
    // 从 c 擦除所有奇数
    for(auto it = c.begin(); it != c.end(); )
        if(it->first % 2 == 1)
            it = c.erase(it);
        else
            ++it;
    for(auto& p : c)
        std::cout << p.second << ' ';
}

swap

  • 交换内容

定义:

void swap( unordered_map& other );

用法:

	std::unordered_map<int, char> a1{{1, 'a'}, {2, 'b'}}, a2{{3, 'c'}};
	a1.swap(a2);

extract

  • 从另一容器释出结点 C++17

定义:

// 解链含 position 所指向元素的结点并返回占有它的结点柄。
node_type extract( const_iterator position );

// 若容器拥有元素而其关键等于 x ,则从容器解链该元素并返回占有它的结点柄。否则,返回空结点柄。
node_type extract( const key_type& x );

merge

  • 从另一容器接合结点 C++17

定义:

template<class C2>
void merge( std::unordered_map<Key, C2, Allocator>& source );

template<class C2>
void merge( std::unordered_map<Key, C2, Allocator>&& source );

用法:

    std::unordered_map<std::string, int>
        p{ {"C", 3}, {"B", 2}, {"A", 1}, {"A", 0} },
        q{ {"E", 6}, {"E", 7}, {"D", 5}, {"A", 4} };
 
    p.merge(q);

// p:  { {E, 6}, {D, 5}, {A, 1}, {B, 2}, {C, 3} }
// q:   { {A, 4} }

查找

at

  • 访问指定的元素,同时进行越界检查
T& at( const Key& key );
const T& at( const Key& key ) const;

operator[]

  • 访问或插入指定的元素
T& operator[]( const Key& key );
T& operator[]( Key&& key );
	std::unordered_map<char, int> letter_counts {{'a', 27}, {'b', 3}, {'c', 1}};
 
    letter_counts['b'] = 42;  // 更新既存值
    letter_counts['x'] = 9;  // 插入新值
 
    for (const auto &pair : letter_counts) {
        std::cout << pair.first << ": " << pair.second << '\n';
    }
 
    // 统计每个词的出现数
    // (首次调用 operator[] 以零初始化计数器)
    std::unordered_map<std::string, size_t>  word_map;
    for (const auto &w : { "this", "sentence", "is", "not", "a", "sentence",
                           "this", "sentence", "is", "a", "hoax"}) {
        ++word_map[w];
    }

count

  • 返回匹配特定键的元素数量
  • 返回拥有关键比较等价于指定参数的元素数。

定义:

size_type count( const Key& key ) const;

template< class K >
size_type count( const K& x ) const;

find

  • 寻找键等于 key 的的元素
  • 返回值
      指向键等于 key 的元素的迭代器。若找不到这种元素,则返回尾后(见 end() )迭代器。

定义:

iterator find( const Key& key );
const_iterator find( const Key& key ) const;

用法:

	std::unordered_map<int,char> example = {{1,'a'},{2,'b'}};
 
    auto search = example.find(2);
    if (search != example.end()) {
        std::cout << "Found " << (*search) << '\n';
    } else {
        std::cout << "Not found\n";
    }

contains

  • 检查容器是否含有带特定键的元素 C++20
  • 若有这种元素则返回 true ,否则返回 false

定义:

bool contains( const Key& key ) const;

template< class K > bool contains( const K& x ) const;

用法:

	 std::unordered_map<int,char> example = {{1,'a'},{2,'b'}};
 
    for(int x: {2, 5}) {
        if(example.contains(x)) {
            std::cout << x << ": Found\n";
        } else {
            std::cout << x << ": Not found\n";
        }
    }

equal_range

  • 返回匹配特定键的元素范围
  • 返回容器中所有键等于 key 的元素范围。范围以二个迭代器定义,第一个指向所需范围的首元素,而第二个指向范围的尾后一位元素

定义:

std::pair<iterator,iterator> equal_range( const Key& key );
    std::unordered_map<int,char> map = {{1,'a'},{1,'b'},{1,'d'},{2,'b'}};
    auto range = map.equal_range(1);
    for (auto it = range.first; it != range.second; ++it) {
        std::cout << it->first << ' ' << it->second << '\n';
    }
    // 输出: 1 a

桶接口

begin、cbegin

  • 返回一个迭代器,指向指定的桶的开始
local_iterator begin( size_type n );
const_local_iterator begin( size_type n ) const;
const_local_iterator cbegin( size_type n ) const;

end、cend

  • 返回一个迭代器,指向指定的桶的末尾
local_iterator end( size_type n );
(C++11)
const_local_iterator end( size_type n ) const;
const_local_iterator cend( size_type n ) const;

bucket_count

  • 返回桶数
size_type bucket_count() const;

max_bucket_count

  • 返回桶的最大数量
size_type max_bucket_count() const;

bucket_size

  • 返回下标为 n 的桶中的元素数
size_type bucket_size( size_type n ) const;

bucket

  • 返回带有特定键的桶
size_type bucket( const Key& key ) const;

哈希策略

load_factor

  • 返回每个桶元素的平均数,即 size() 除以 bucket_count()
float load_factor() const;

max_load_factor

  • 管理最大加载因子(每个桶的平均元素数)。若加载因子超出此阈值,则容器自动增加桶数。
// 返回最大加载因子
float max_load_factor() const;

// 设置最大加载因子为 ml
void max_load_factor( float ml );

rehash

  • 设置桶数为 count 并重哈希容器,即考虑桶总数已改变,再把元素放到适当的桶中。
  • 若新的桶数使加载因子大于最大加载因子( count < size() / max_load_factor() ),则新桶数至少为 size() / max_load_factor()
void rehash( size_type count );

reserve

  • 设置桶数为适应至少 count 个元素,而不超出最大加载因子所需的数,并重哈希容器,即考虑桶数已更改后将元素放进适合的桶。等效地调用 rehash(std::ceil(count / max_load_factor())) 。
void reserve( size_type count );

观察器

hash_function

  • 返回对关键哈希的函数
hasher hash_function() const;

key_eq

  • 返回比较关键相等性的函数
key_equal key_eq() const;

非成员函数

operator==

  • 比较 unordered_map 中的值

定义:

template< class Key, class Hash, class KeyEqual, class Allocator >
bool operator==( const std::unordered_map<Key,Hash,KeyEqual,Allocator>& lhs,
                 const std::unordered_map<Key,Hash,KeyEqual,Allocator>& rhs );

用法:

	std::unordered_map<int, char> alice{{1, 'a'}, {2, 'b'}};
	std::unordered_map<int, char> bob{{1, 'a'}, {3, 'c'}};
	std::unordered_map<int, char> eve{1, 'a'}, {2, 'b'}};
 
	// 比较不相等的容器
	std::cout << "alice == bob returns " << (alice == bob) << std::endl;	//输出 false
	// 比较相等的容器
	std::cout << "alice == eve returns " << (alice == eve) << std::endl;	//输出 true

std::swap

  • 为 std::unordered_map 特化 std::swap 算法。交换 lhs 与 rhs 的内容。调用 lhs.swap(rhs) 。

定义:

template< class Key, class T, class Hash, class KeyEqual, class Alloc >
void swap( std::unordered_map<Key,T,Hash,KeyEqual,Alloc>& lhs,
           std::unordered_map<Key,T,Hash,KeyEqual,Alloc>& rhs ););

用法:

    std::unordered_map<int, char> alice{{1, 'a'}, {2, 'b'}, {3, 'c'}};
    std::unordered_map<int, char> bob{{7, 'Z'}, {8, 'Y'}, {9, 'X'}, {10, 'W'}};
	//交换容器
	std::swap(alice,bob);
	//交换后:alice : 7 8 9 10	bob : 1 2 3

erase_if(std::unordered_map)

  • 擦除所有满足特定判别标准的元素(C++ 20)

定义:

template< class Key, class T, class Hash, class KeyEqual, class Alloc, class Pred >
typename std::unordered_map<Key,T,Hash,KeyEqual,Alloc>::size_type
    erase_if(std::unordered_map<Key,T,Hash,KeyEqual,Alloc>& c, Pred pred);

用法:

	std::unordered_map<int, char> data {{1, 'a'},{2, 'b'},{3, 'c'},{4, 'd'},
                                        {5, 'e'},{4, 'f'},{5, 'g'},{5, 'g'}};
	const auto count = std::erase_if(data, [](const auto& item) {
        auto const& [key, value] = item;
        return (key & 1) == 1;
    });
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
multimap是一个允许元素重复的关联容器,它的内部实现也是使用红黑树。它可以在插入时按照特定的顺序进行排序,并且可以包含相同的键。在C++中,我们可以使用multimap来存储一组键值对,其中键可以重复。例如,我们可以使用multimap来存储不同班级的学生名字,每个班级可能有多个相同名字的学生。使用multimap时,我们可以通过迭代器遍历其中的元素。 unordered_map是一个使用哈希表实现的关联容器,它不允许重复的键。与multimap不同,unordered_map不会对元素进行排序。它的插入和查找操作的时间复杂度都是O(1)。unordered_map适用于需要快速查找和插入元素的情况。例如,我们可以使用unordered_map来存储员工的姓名和工资,通过姓名快速查找对应的工资。使用unordered_map时,我们可以使用迭代器遍历其中的元素。 所以,如果你需要允许重复的键并且需要按照特定顺序来存储元素,你可以使用multimap。如果你不需要重复的键并且希望在常量时间内进行查找和插入操作,你可以使用unordered_map。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++ STL multimap与unordered_map](https://blog.csdn.net/yao_hou/article/details/107419196)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [C++ STL库中的multimap和unordered_multimap](https://blog.csdn.net/Woosual/article/details/107884396)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值