C++ multimap使用
multimap
概述
- 定义于头文件<map>
- std::multimap 是有序键值对容器,它的元素的键是唯一的。用比较函数 Compare 排序键。搜索、移除和插入操作拥有对数复杂度。 multimap 通常实现为红黑树。
类模板:
template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
> class multimap;
创建multimap
构造函数
定义:
// 1、默认构造函数
multimap();
// 2、范围构造函数。构造拥有范围 [first, last) 内容的容器。若范围中的多个元素拥有比较等价的关键,则插入哪个元素是未指定的
template< class InputIt >
multimap( InputIt first, InputIt last,
const Compare& comp = Compare(),
const Allocator& alloc = Allocator() );
// 3、复制构造函数
multimap( const multimap& other );
// 4、移动构造函数
multimap( multimap&& other );
// 5、initializer_multimap init 构造函数
multimap( std::initializer_list<value_type> init,
const Compare& comp = Compare(),
const Allocator& alloc = Allocator() );
用法:
#include <iostream>
#include <string>
#include <iomanip>
#include <multimap>
template<typename Multimap>
void print_multimap(Multimap& m)
{
std::cout << '{';
for(auto& p: m)
std::cout << p.first << ':' << p.second << ' ';
std::cout << "}\n";
}
struct Point { double x, y; };
struct PointCmp {
bool operator()(const Point& lhs, const Point& rhs) const {
return lhs.x < rhs.x; // NB 。有意忽略 y
}
};
int main()
{
// (1) 默认构造函数
std::multimap<std::string, int> multimap1;
multimap1["something"] = 69;
multimap1["anything"] = 199;
multimap1["that thing"] = 50;
std::cout << "multimap1 = "; print_multimap(multimap1);
// (2) 范围构造函数
std::multimap<std::string, int> iter(multimap1.find("anything"), multimap1.end());
std::cout << "\niter = "; print_multimap(iter);
std::cout << "multimap1 = "; print_multimap(multimap1);
// (3) 复制构造函数
std::multimap<std::string, int> copied(multimap1);
std::cout << "\ncopied = "; print_multimap(copied);
std::cout << "multimap1 = "; print_multimap(multimap1);
// (4) 移动构造函数
std::multimap<std::string, int> moved(std::move(multimap1));
std::cout << "\nmoved = "; print_multimap(moved);
std::cout << "multimap1 = "; print_multimap(multimap1);
// (5) initializer_list 构造函数
const std::multimap<std::string, int> init {
{"this", 100},
{"can", 100},
{"be", 100},
{"const", 100},
};
std::cout << "\ninit = "; print_multimap(init);
// 定制关键类选项 1 :
// 使用比较 struct
std::multimap<Point, double, PointCmp> mag = {
{ {5, -12}, 13 },
{ {3, 4}, 5 },
{ {-8, -15}, 17 }
};
for(auto p : mag)
std::cout << "The magnitude of (" << p.first.x
<< ", " << p.first.y << ") is "
<< p.second << '\n';
// 定制关键类选项 2 :
// 使用比较 lambda
// 此 lambda 按照其模比较点,注意其中模取自局部变量 mag
auto cmpLambda = [&mag](const Point &lhs, const Point &rhs) { return mag[lhs] < mag[rhs]; };
// 你亦可使用不依赖局部变量的 lambda ,像这样:
// auto cmpLambda = [](const Point &lhs, const Point &rhs) { return lhs.y < rhs.y; };
std::multimap<Point, double, decltype(cmpLambda)> magy(cmpLambda);
// 各种插入元素的方式:
magy.insert(std::pair<Point, double>({5, -12}, 13));
magy.insert({ {3, 4}, 5});
magy.insert({Point{-8.0, -15.0}, 17});
std::cout << '\n';
for(auto p : magy)
std::cout << "The magnitude of (" << p.first.x
<< ", " << p.first.y << ") is "
<< p.second << '\n';
}
// 输出
// multimap1 = {anything:199 something:69 that thing:50 }
// iter = {anything:199 something:69 that thing:50 }
// multimap1 = {anything:199 something:69 that thing:50 }
// copied = {anything:199 something:69 that thing:50 }
// multimap1 = {anything:199 something:69 that thing:50 }
// moved = {anything:199 something:69 that thing:50 }
// multimap1 = {}
// init = {be:100 can:100 const:100 this:100 }
// The magnitude of (-8, -15) is 17
// The magnitude of (3, 4) is 5
// The magnitude of (5, -12) is 13
// The magnitude of (3, 4) is 5
// The magnitude of (5, -12) is 13
// The magnitude of (-8, -15) is 17
opertor=
- 赋值给容器
定义:
multimap& operator=( const multimap& other ); // 复制赋值运算符。
multimap& operator=( multimap&& other ); // 移动赋值运算符。
multimap& operator=( std::initializer_multimap<T> imultimap ); // 以 initializer_multimap imultimap 所标识者替换内容。
用法:
std::multimap<int, int> nums1 {{3, 1}, {4, 1}, {5, 9},
{6, 1}, {7, 1}, {8, 9}};
std::multimap<int, int> nums2;
std::multimap<int, int> nums3;
// 从 nums1 复制赋值数据到 nums2
nums2 = nums1;
// 从 nums1 移动赋值数据到 nums3,
nums3 = std::move(nums1);
// initializer_multimap 的复制赋值复制数据给 nums1
nums1 = {{3, 1}, {4, 1}, {5, 9}};
元素访问
at
- 访问指定的元素,同时进行越界检查
T& at( const Key& key );
const T& at( const Key& key ) const;
- 参数:key - 要找到的元素的键
- 返回值:value,键对应的值
operator[ ]
- 访问或插入指定的元素
定义:
T& operator[]( const Key& key );
T& operator[]( Key&& key );
用法:
#include <iostream>
#include <string>
#include <vector>
#include <multimap>
int main()
{
std::multimap<char, int> letter_counts {{'a', 27}, {'b', 3}, {'c', 1}};
std::cout << "initially:\n";
for (const auto &pair : letter_counts) {
std::cout << pair.first << ": " << pair.second << '\n';
}
letter_counts['b'] = 42; // 更新既存值
letter_counts['x'] = 9; // 插入新值
std::cout << "after modifications:\n";
for (const auto &pair : letter_counts) {
std::cout << pair.first << ": " << pair.second << '\n';
}
// 统计每个词的出现数
// (首次调用 operator[] 以零初始化计数器)
std::multimap<std::string, size_t> word_multimap;
for (const auto &w : { "this", "sentence", "is", "not", "a", "sentence",
"this", "sentence", "is", "a", "hoax"}) {
++word_multimap[w];
}
for (const auto &pair : word_multimap) {
std::cout << pair.second << " occurrences of word '" << pair.first << "'\n";
}
}
// 输出
initially:
a: 27
b: 3
c: 1
after modifications:
a: 27
b: 42
c: 1
x: 9
2 occurrences of word 'a'
1 occurrences of word 'hoax'
2 occurrences of word 'is'
1 occurrences of word 'not'
3 occurrences of word 'sentence'
2 occurrences of word 'this'
迭代器
begin\cbegin
- 返回指向 multimap 首元素的迭代器。
- cbegin中的c表示const,即返回const_iterator,不允许通过迭代器修改元素。
- 若 multimap 为空,则返回的迭代器将等于 end() 。
定义:
iterator begin();
const_iterator cbegin() const noexcept;
用法:
#include <iostream>
#include <multimap>
int main() {
std::multimap<int, float> num_multimap;
num_multimap[4] = 4.13;
num_multimap[9] = 9.24;
num_multimap[1] = 1.09;
// 调用 a_multimap.begin() 与 a_multimap.end()
for (auto it = num_multimap.begin(); it != num_multimap.end(); ++it) {
std::cout << it->first << ", " << it->second << '\n';
}
}
// 输出
// 1, 1.09
// 4, 4.13
// 9, 9.24
end\cend
- 返回指向 multimap 末元素后一元素的迭代器。
定义:
iterator end();
const_iterator cend() const noexcept;
rbegin\crbegin
- 返回指向逆向 multimap 首元素的逆向迭代器。
- 它对应非逆向 multimap 的末元素。若 multimap 为空,则返回的迭代器等于 rend() 。
定义:
reverse_iterator rbegin();
const_reverse_iterator crbegin() const noexcept;
rend\crend
- 返回指向逆向 multimap 末元素后一元素的逆向迭代器。
- 它对应非逆向 multimap 首元素的前一元素。此元素表现为占位符,试图访问它导致未定义行为。
定义:
reverse_iterator rend();
const_reverse_iterator crend() const noexcept;
容量
empty
- 检查容器是否无元素,即是否 begin() == end() 。
定义:
bool empty() const;
用法:
multimap<int, int> v;
bool flag = v.empty(); // 输出 true
size
- 返回容纳的元素数。 即 std::distance(begin(), end()) 。
定义:
size_type size() const;
用法:
std::multimap<int,char> nums {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};
std::cout << nums.size() << std::endl; // 输出 4
max_size
- 返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end()) 。
定义:
size_type max_size() const;
用法:
std::multimap<int, int> vi;
std::cout << vi.max_size() << std::endl; // 可能输出 4611686018427387903
std::multimap<char, cahr> vc;
std::cout << vc.max_size() << std::endl; // 可能输出 18446744073709551615
修改器
clear
- 从容器擦除所有元素。此调用后 size() 返回零。
- 非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器亦被非法化。
定义:
void clear();
用法:
std::multimap<int, char> container{{1, 'a'}, {3, 'b'}, {5, 'c'}};
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::multimap<int, char> a;
a.insert({1, 'a'});
std::multimap<int, char> b { {3, 'b'}, {5, 'c'}};
a.insert(b.begin(), b.end());
a.insert({7, 'd'}, {9, 'e'});
emplace
原位构造元素
定义:
template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );;
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 )
用法:
std::multimap<int, char> c = {{3, 'b'}, {4, 'c'}, {2, 'b'}, {5, 'c'}};
// 从 c 擦除所有奇数
for(auto it = c.begin(); it != c.end(); )
if(it->first % 2 == 1)
it = c.erase(it);
else
++it;
// c : 2 4 6 8
swap
- 交换内容
定义:
void swap( multimap& other );
用法:
std::multimap<int, char> a1{{3, 'b'}}, a2{{4, 'c'}, {2, 'b'}};
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::multimap<Key, C2, Allocator>& source );
template<class C2>
void merge( std::multimap<Key, C2, Allocator>&& source );
用法:
std::multimap<int, std::string> ma {{1, "apple"}, {5, "pear"}, {10, "banana"}};
std::multimap<int, std::string> mb {{2, "zorro"}, {4, "batman"}, {5, "X"}, {8, "alpaca"}};
std::multimap<int, std::string> u;
u.merge(ma);
std::cout << "ma.size(): " << ma.size() << '\n';
u.merge(mb);
std::cout << "mb.size(): " << mb.size() << '\n';
std::cout << "mb.at(5): " << mb.at(5) << '\n';
for(auto const &kv: u)
std::cout << kv.first << ", " << kv.second << '\n';
// 输出
ma.size(): 0
mb.size(): 1
mb.at(5): X
1, apple
2, zorro
4, batman
5, pear
8, alpaca
10, banana
查找
count
- 返回匹配特定键的元素数量
- 返回拥有关键比较等价于指定参数的元素数,因为此容器不允许重复故为 1 或 0。
定义:
size_type count( const Key& key ) const;
find
- 寻找带有特定键的元素
- 返回值
指向键等于 key 的元素的迭代器。若找不到这种元素,则返回尾后(见 end() )迭代器。
定义:
iterator find( const Key& key );
const_iterator find( const Key& key ) const;
用法:
std::multimap<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
- 检查容器中是否有键等价于 key 的元素
- 若有这种元素则返回 true ,否则返回 false
定义:
bool contains( const Key& key ) const;
template< class K > bool contains( const K& x ) const;
用法:
std::multimap<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 的元素,另一个指向首个大于 key 的元素。首个迭代器可以换用 lower_bound() 获得,而第二迭代器可换用 upper_bound() 获得。
- 返回值: 含一对定义所需范围的迭代器的 std::pair :第一个指向首个不小于 key 的元素,第二个指向首个大于 key 的元素。
若无元素不小于 key ,则将尾后(见 end() )迭代器作为第一元素返回。类似地,若无元素大于 key ,则将尾后迭代器作为第二元素返回。
定义:
std::pair<iterator,iterator> equal_range( const Key& key );
lower_bound
- 返回指向首个不小于给定键的元素的迭代器
- 指向首个不小于 key 的元素的迭代器。若找不到这种元素,则返回尾后迭代器。
定义:
iterator lower_bound( const Key& key );
用法见upper_bound。
upper_bound
- 返回指向首个大于给定键的元素的迭代器
- 指向首个大于 key 的元素的迭代器。若找不到这种元素,则返回尾后(见 end() )迭代器。
定义:
iterator upper_bound( const Key& key );
用法:
std::multimap<int, char> a {{1,'a'},{2,'b'}, {3,'c'}, {4,'d'}};
std::cout << a.lower_bound(3)->second << std::endl; // 3
std::cout << a.upper_bound(3) << std::endl; // 4
观察器
key_comp
- 返回用于比较键的函数
- 它是此容器构造函数参数 comp 的副本,它与 value_comp 相同。
key_compare key_comp() const;
value_comp
- 返回比较 std::multimap::value_type (关键-值 pair )对象的函数对象,它用 key_comp 比较 pair 的第一组分。
- 返回值
比较值的函数对象。
std::multimap::value_compare value_comp() const;
非成员函数
operator==
- 按照字典顺序比较 multimap 中的值
定义:
template< class Key, class Compare, class Alloc >
bool operator==( const std::multimap<Key,Compare,Alloc>& lhs,
const std::multimap<Key,Compare,Alloc>& rhs );
用法:
std::multimap<int, char> alice{{1, 'a'}, {2, 'b'}, {3, 'c'}};
std::multimap<int, char> bob{{7, 'Z'}, {8, 'Y'}, {9, 'X'}, {10, 'W'}};
std::multimap<int, char> eve{{1, 'a'}, {2, 'b'}, {3, 'c'}};
// 比较不相等的容器
std::cout << "alice == bob returns " << (alice == bob) << std::endl; //输出 false
// 比较相等的容器
std::cout << "alice == eve returns " << (alice == eve) << std::endl; //输出 true
std::swap(std::multimap)
- 为 std::multimap 特化 std::swap 算法。交换 lhs 与 rhs 的内容。调用 lhs.swap(rhs) 。
定义:
template< class Key, class Compare, class Alloc >
void swap( std::multimap<Key,Compare,Alloc>& lhs,
std::multimap<Key,Compare,Alloc>& rhs );
用法:
std::multimap<int, char> alice{{1, 'a'}, {2, 'b'}, {3, 'c'}};
std::multimap<int, char> bob{{7, 'Z'}, {8, 'Y'}, {9, 'X'}, {10, 'W'}};
//交换容器
std::swap(alice,bob);
erase_if(std::multimap)
- 擦除所有满足特定判别标准的元素(C++ 20)
定义:
template< class Key, class Compare, class Alloc, class Pred >
typename std::multimap<Key,Compare,Alloc>::size_type
erase_if(std::multimap<Key,Compare,Alloc>& c, Pred pred);
用法:
std::multimap<int, char> data {{1, 'a'},{2, 'b'},{3, 'c'},{4, 'd'},
{5, 'e'},{4, 'f'},{5, 'g'},{5, 'g'}};
std::cout << "Original:\n" << data << '\n';
const auto count = std::erase_if(data, [](const auto& item) {
auto const& [key, value] = item;
return (key & 1) == 1;
});
// {{2, b}{4, d}}