// unordered_multimap 模板定义
template, class KeyEqual = std::equal_to,
class Allocator = std::allocator< std::pair>> class unordered_multimap; (C++11 起)
namespace pmr {
template , class Pred = std::equal_to>
using unordered_multimap = std::unordered_multimap>>;(C++17 起)
}
#include
#include
#include
#include
#include
auto Print(const std::string &msg,
const std::unordered_multimap &lst) {
std::cout << msg << " : ";
for (const auto &pa : lst) {
std::cout << pa.first << " -> " << pa.second << "\t";
}
std::cout << "\n";
}
struct Key {
int first;
int second;
}; // 自定义Key 结构
struct KeyHash {
std::size_t operator()(const Key &k) const {
return std::hash{}(k.first) ^ (std::hash{}(k.second) << 1);
}
}; // 自定义哈希结构
struct KeyEqual {
bool operator()(const Key &lhs, const Key &rhs) const {
return lhs.first == rhs.first && lhs.second == rhs.second;
}
}; // 自定义 Key 比较结构
// 自定义 Key 打印函数
auto Print(const std::string &msg,
const std::unordered_multimap &lst) {
std::cout << msg << " : ";
for (const auto &pa : lst) {
std::cout << pa.first.first << ":" << pa.first.second << " -> " << pa.second
<< "\t";
}
std::cout << "\n";
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
using umap_int = std::unordered_multimap;
umap_int m1; //默认构造
Print("m1", m1);
umap_int m2(10); //设置桶数量
Print("m2", m2);
std::allocator> alloc;
std::unordered_multimap m3(10, KeyHash(),
KeyEqual(), alloc);
Print("m3", m3);
umap_int m4(10, alloc); //设置桶数量和分配器
Print("m4", m4);
umap_int m5(alloc); //设置分配器
Print("m5", m5);
umap_int m6{{1, 10}, {2, 20}, {3, 30}, {3, 50}}; //初始化列表
Print("m6", m6);
umap_int m7(m6.begin(), m6.end()); //迭代器初始化,基于范围
Print("m7", m7);
std::unordered_multimap m8 = {
{{1, 10}, 100},
{{2, 20}, 200},
{{3, 30}, 300},
{{3, 30}, 400}}; //初始化列表
Print("m8", m8);
std::unordered_multimap m9(
m8.begin(), m8.end(), 10, KeyHash(), KeyEqual(),
alloc); //迭代器初始化,基于范围
Print("m9", m9);
umap_int m10 = {{3, 1}, {4, 1}, {5, 9}, {5, 6}}; //初始化列表
Print("m10", m10);
umap_int m11(m10); //拷贝构造初始化,可设置分配器
Print("m11", m11);
umap_int m12(m11, alloc);
Print("m12", m12);
umap_int m13(std::move(m12)); //移动构造初始化,可设置分配器
Print("m13", m13);
umap_int m14(std::move(m13), alloc);
Print("m14", m14);
//析构函数默认
return 0; // a.exec();
}
输出结果:
m1 :
m2 :
m3 :
m4 :
m5 :
m6 : 1 -> 10 2 -> 20 3 -> 30 3 -> 50
m7 : 1 -> 10 2 -> 20 3 -> 30 3 -> 50
m8 : 1:10 -> 100 2:20 -> 200 3:30 -> 300 3:30 -> 400
m9 : 1:10 -> 100 2:20 -> 200 3:30 -> 300 3:30 -> 400
m10 : 3 -> 1 4 -> 1 5 -> 9 5 -> 6
m11 : 3 -> 1 4 -> 1 5 -> 9 5 -> 6
m12 : 3 -> 1 4 -> 1 5 -> 9 5 -> 6
m13 : 3 -> 1 4 -> 1 5 -> 9 5 -> 6
m14 : 3 -> 1 4 -> 1 5 -> 9 5 -> 6
auto Print(const std::string &msg,
const std::unordered_multimap &lst) {
std::cout << msg << " : ";
for (const auto &pa : lst) {
std::cout << pa.first << " -> " << pa.second << "\t";
}
std::cout << "\n";
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
using umap_int = std::unordered_multimap;
umap_int m1{{1, 10}, {2, 20}, {2, 30}, {3, 30}};
Print("m1", m1);
std::cout << "m1 : ";
for (const auto &pa : m1) {
std::cout << pa.first << " -> " << pa.second << "\t";
}
std::cout << "\n";
return 0; // a.exec();
}
输出结果:
m1 : 1 -> 10 2 -> 20 2 -> 30 3 -> 30
m1 : 1 -> 10 2 -> 20 2 -> 30 3 -> 30
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
using umap_int = std::unordered_multimap;
umap_int m1{{1, 10}, {2, 20}, {2, 30}, {3, 30}};
umap_int::iterator iter = m1.begin(); // 返回指向起始的迭代器
std::cout << "m1 : ";
for (; iter != m1.end(); ++iter) {
std::cout << iter->first << " -> " << iter->second << "\t";
}
std::cout << '\n';
umap_int::const_iterator citer = m1.begin(); // 返回指向起始的迭代器,const
std::cout << "m1 : ";
for (; citer != m1.end(); ++citer) {
std::cout << citer->first << " -> " << citer->second << "\t";
}
std::cout << '\n';
return 0; // a.exec();
}
输出结果:
m1 : 1 -> 10 2 -> 20 2 -> 30 3 -> 30
m1 : 1 -> 10 2 -> 20 2 -> 30 3 -> 30
auto Print(const std::string &msg, const std::unordered_multimap &lst) {
std::cout << msg << " : ";
for (const auto &pa : lst) {
std::cout << pa.first << " -> " << pa.second << "\t";
}
std::cout << "\n";
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
using umap_int = std::unordered_multimap;
umap_int m1{{1, 10}, {2, 20}, {2, 30}, {3, 30}};
Print("m1", m1);
//检查容器是否为空
std::cout << std::boolalpha << "m1.empty() : " << m1.empty() << std::endl;
std::cout << "m1.size() : " << m1.size() << std::endl; //返回容纳的元素数
std::cout << "m1.max_size() : " << m1.max_size() << std::endl; //返回可容纳的最大元素数,和平台有关
return 0; // a.exec();
}
输出结果:
m1 : 1 -> 10 2 -> 20 2 -> 30 3 -> 30
s1.empty() : false
s1.size() : 4
s1.max_size() : 768614336404564650
auto Print(const std::string &msg,
const std::unordered_multimap &lst) {
std::cout << msg << " : ";
for (const auto &pa : lst) {
std::cout << pa.first << " -> " << pa.second << "\t";
}
std::cout << "\n";
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
using umap_int = std::unordered_multimap;
umap_int m1{{1, 10}, {2, 20}, {2, 30}, {3, 30}};
Print("m1", m1);
m1.clear(); // 清除内容
Print("m1", m1);
m1.insert({10, 100}); //插入元素或结点
Print("m1", m1);
m1.emplace(20, 200); //原位构造元素
Print("m1", m1);
m1.emplace_hint(m1.end(), 30, 300); //使用提示原位构造元素
Print("m1", m1);
m1.erase(m1.begin()); //擦除元素
Print("m1", m1);
umap_int m2;
m2.swap(m1);
Print("m1", m1);
Print("m2", m2);
return 0; // a.exec();
}
输出结果:
m1 : 1 -> 10 2 -> 20 2 -> 30 3 -> 30
m1 :
m1 : 10 -> 100
m1 : 10 -> 100 20 -> 200
m1 : 10 -> 100 20 -> 200 30 -> 300
m1 : 20 -> 200 30 -> 300
m1 :
m2 : 20 -> 200 30 -> 300
auto Print(const std::string &msg,
const std::unordered_multimap &lst) {
std::cout << msg << " : ";
for (const auto &pa : lst) {
std::cout << pa.first << " -> " << pa.second << "\t";
}
std::cout << "\n";
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
using umap_int = std::unordered_multimap;
umap_int m1{{1, 10}, {2, 20}, {2, 30}, {3, 30}, {3, 40}};
Print("m1", m1);
// 返回匹配特定键的元素数量
std::cout << "m1.count(1) : " << m1.count(1) << std::endl;
std::cout << "m1.count(2) : " << m1.count(2) << std::endl;
std::cout << "m1.count(3) : " << m1.count(3) << std::endl;
// 寻找带有特定键的元素,返回 key 对应的任意一个值的迭代器
umap_int::const_iterator iter = m1.find(3);
if (iter != m1.cend()) {
std::cout << "m1.find(3) : " << iter->first << " -> " << iter->second
<< std::endl;
} else {
std::cout << "m1.find(3) : m1.cend()" << std::endl;
}
// 返回容器中所有键等于 key 的元素范围
// 返回容器中所有键等于 key
// 的元素范围。范围以二个迭代器定义,第一个指向所需范围的首元素,而第二个指向范围的尾后一位元素。
// 返回含有容器中所有键等价于 x 的元素的范围。此重载只有在有限定标识
// Hash::is_transparent 与 KeyEqual::is_transparent
// 均合法并指代类型时才参与重载决议。这假设能用 K 和 Key 类型一起调用这种 Hash
// 还有 KeyEqual 是通透的,进而允许不用构造 Key 的实例就调用此函数
std::pair pa = m1.equal_range(3);
if (pa.first == m1.end())
std::cout << "pa.first is empty" << std::endl;
else
std::cout << "m1.equal_range(3) first : " << pa.first->first << " -> "
<< pa.first->second << std::endl;
if (pa.second == m1.end())
std::cout << "pa.second is empty" << std::endl;
else
std::cout << "m1.equal_range(3) second : " << pa.second->first << " -> "
<< pa.second->second << std::endl;
return 0; // a.exec();
}
输出结果:
m1.count(3) : 2
m1.find(3) : 3 -> 30
m1.equal_range(3) first : 3 -> 30
pa.second is empty
auto Print(const std::string &msg,
const std::unordered_multimap &lst) {
std::cout << msg << " : ";
for (const auto &pa : lst) {
std::cout << pa.first << " -> " << pa.second << "\t";
}
std::cout << "\n";
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
using umap_int = std::unordered_multimap;
umap_int m1{{1, 10}, {2, 20}, {3, 30}};
umap_int m2{{1, 10}, {2, 20}, {2, 30}, {3, 30}, {3, 40}};
Print("m1", m1);
Print("m2", m2);
std::cout << std::boolalpha << "m1 == m2 : " << (m1 == m2) << std::endl;
umap_int m3;
std::swap(m3, m2);
Print("m2", m2);
Print("m3", m3);
return 0; // a.exec();
}
输出结果:
m1 : 1 -> 10 2 -> 20 3 -> 30
m2 : 1 -> 10 2 -> 20 2 -> 30 3 -> 30 3 -> 40
m1 == m2 : false
m2 :
m3 : 1 -> 10 2 -> 20 2 -> 30 3 -> 30 3 -> 40
auto Print(const std::string &msg,
const std::unordered_multimap &lst) {
std::cout << msg << " : ";
for (const auto &pa : lst) {
std::cout << pa.first << " -> " << pa.second << "\t";
}
std::cout << "\n";
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
using umap_int = std::unordered_multimap;
umap_int m1;
m1.emplace(1, 2);
m1.emplace(10, 20);
m1.emplace(100, 200);
m1.emplace(1000, 2000);
m1.emplace(1000, 3000);
Print("m1", m1);
//返回一个迭代器,指向指定的桶的开始
for (int i = 0; i < m1.bucket_count(); ++i) {
auto iter = m1.begin(i);
if (iter == m1.end(i)) {
std::cout << "m1.end(" << i << ")"
<< "\t";
} else {
for (; iter != m1.end(i); ++iter) {
std::cout << "m1.begin(" << i << ") : " << iter->first << " -> "
<< iter->second << "\t";
}
}
}
std::cout << "\n";
//返回一个迭代器,指向指定的桶的开始
for (int i = 0; i < m1.bucket_count(); ++i) {
auto iter = m1.cbegin(i);
if (iter == m1.cend(i)) {
std::cout << "m1.cend(" << i << ")"
<< "\t";
} else {
for (; iter != m1.cend(i); ++iter) {
std::cout << "m1.cbegin(" << i << ") : " << iter->first << " -> "
<< iter->second << "\t";
}
}
}
std::cout << "\n";
//返回桶数
std::cout << "m1.bucket_count() : " << m1.bucket_count() << std::endl;
//返回桶的最大数量
std::cout << "m1.max_bucket_count() : " << m1.max_bucket_count() << std::endl;
//返回在特定的桶中的元素数量
for (int i = 0; i < m1.bucket_count(); ++i) {
std::cout << "m1.bucket_size(" << i << ") : " << m1.bucket_size(i) << "\t";
}
std::cout << "\n";
//返回带有特定键的桶,返回关键 key 的桶的下标。始终会在此桶中找到关键等于 key
//的元素(若存在)。返回值仅对 bucket_count() 返回相同值的容器实例合法。
//若 bucket_count() 为零则行为未定义
std::cout << "m1.bucket(1) : " << m1.bucket(1) << std::endl;
std::cout << "m1.bucket(100) : " << m1.bucket(100) << std::endl;
// 键不存在,若存在会分配当前下标的桶
std::cout << "m1.bucket(5000) : " << m1.bucket(5000) << std::endl;
std::cout << "m1.bucket(2) : " << m1.bucket(2) << std::endl;
return 0; // a.exec();
}
输出结果:
m1.cend(0) m1.cbegin(1) : 100 -> 200 m1.cend(2) m1.cend(3) m1.cbegin(4) : 1000 -> 2000 m1.cbegin(4) : 1000 -> 3000 m1.cbegin(4) : 1 -> 2 m1.cend(5) m1.cend(6) m1.cbegin(7) : 10 -> 20
m1.bucket_count() : 8
m1.max_bucket_count() : 1152921504606846975
m1.bucket_size(0) : 0 m1.bucket_size(1) : 1 m1.bucket_size(2) : 0 m1.bucket_size(3) : 0 m1.bucket_size(4) : 3 m1.bucket_size(5) : 0 m1.bucket_size(6) : 0 m1.bucket_size(7) : 1
m1.bucket(1) : 4
m1.bucket(100) : 1
m1.bucket(5000) : 4
m1.bucket(2) : 7
auto Print(const std::string &msg,
const std::unordered_multimap &lst) {
std::cout << msg << " : ";
for (const auto &pa : lst) {
std::cout << pa.first << " -> " << pa.second << "\t";
}
std::cout << "\n";
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
using umap_int = std::unordered_multimap;
umap_int m1;
m1.emplace(1, 2);
m1.emplace(10, 20);
m1.emplace(100, 200);
m1.emplace(1000, 2000);
m1.emplace(1000, 3000);
Print("m1", m1);
for (int i = 0; i < m1.bucket_count(); ++i) {
auto iter = m1.begin(i);
if (iter == m1.end(i)) {
std::cout << "m1.end(" << i << ")"
<< "\t";
} else {
for (; iter != m1.end(i); ++iter) {
std::cout << "m1.begin(" << i << ") : " << iter->first << " -> "
<< iter->second << "\t";
}
}
}
std::cout << "\n";
//返回每个桶的平均元素数量
std::cout << "m1.load_factor() : " << m1.load_factor() << std::endl;
for (int i = 0; i < m1.bucket_count(); ++i) {
}
//管理每个桶的平均元素数量的最大值
//管理最大加载因子(每个桶的平均元素数)。若加载因子超出此阈值,则容器自动增加桶数
//返回最大加载因子
std::cout << "m1.max_load_factor() : " << m1.max_load_factor() << std::endl;
//设置最大加载因子
m1.max_load_factor(0.9);
std::cout << "m1.max_load_factor() : " << m1.max_load_factor() << std::endl;
//为至少为指定数量的桶预留存储空间并重新生成散列表
//设置桶数为 count并重哈希容器,即考虑桶总数已改变,再把元素放到适当的桶中
//若新的桶数使加载因子大于最大加载因子( count < size() / max_load_factor() )
//则新桶数至少为 size() / max_load_factor()
m1.rehash(16);
for (int i = 0; i < m1.bucket_count(); ++i) {
auto iter = m1.begin(i);
if (iter == m1.end(i)) {
std::cout << "m1.end(" << i << ")"
<< "\t";
} else {
for (; iter != m1.end(i); ++iter) {
std::cout << "m1.begin(" << i << ") : " << iter->first << " -> "
<< iter->second << "\t";
}
}
}
std::cout << "\n";
//为至少为指定数量的元素预留存储空间并重新生成哈希表
//设置桶数为适应至少 count 个元素,而不超出最大加载因子所需的数
//并重哈希容器,即考虑桶数已更改后将元素放进适合的桶
//等效地调用 rehash(std::ceil(count / max_load_factor()))
m1.reserve(20);
for (int i = 0; i < m1.bucket_count(); ++i) {
auto iter = m1.begin(i);
if (iter == m1.end(i)) {
std::cout << "m1.end(" << i << ")"
<< "\t";
} else {
for (; iter != m1.end(i); ++iter) {
std::cout << "m1.begin(" << i << ") : " << iter->first << " -> "
<< iter->second << "\t";
}
}
}
std::cout << "\n";
return 0; // a.exec();
}
输出结果:
m1 : 1000 -> 2000 1000 -> 3000 1 -> 2 10 -> 20 100 -> 200
m1.end(0) m1.begin(1) : 100 -> 200 m1.end(2) m1.end(3) m1.begin(4) : 1000 -> 2000 m1.begin(4) : 1000 -> 3000 m1.begin(4) : 1 -> 2 m1.end(5) m1.end(6) m1.begin(7) : 10 -> 20
m1.load_factor() : 0.625
m1.max_load_factor() : 1
m1.max_load_factor() : 0.9
m1.end(0) m1.begin(1) : 100 -> 200 m1.end(2) m1.end(3) m1.begin(4) : 1 -> 2 m1.end(5) m1.end(6) m1.end(7) m1.end(8) m1.end(9) m1.end(10) m1.end(11) m1.begin(12) : 1000 -> 2000 m1.begin(12) : 1000 -> 3000 m1.end(13) m1.end(14) m1.begin(15) : 10 -> 20
m1.end(0) m1.end(1) m1.end(2) m1.end(3) m1.begin(4) : 1 -> 2 m1.end(5) m1.end(6) m1.end(7) m1.end(8) m1.end(9) m1.end(10) m1.end(11) m1.end(12) m1.end(13) m1.end(14) m1.end(15) m1.end(16) m1.begin(17) : 100 -> 200 m1.end(18) m1.end(19) m1.end(20) m1.end(21) m1.end(22) m1.end(23) m1.end(24) m1.end(25) m1.end(26) m1.end(27) m1.begin(28) : 1000 -> 2000 m1.begin(28) : 1000 -> 3000 m1.end(29) m1.end(30) m1.begin(31) : 10 -> 20
起始