突破编程_C++_C++11新特性(unordered_multimap)
1 概述
std::unordered_multimap 是一个哈希表实现的无序容器,它存储的元素是键值对,并且允许键的重复。这意味着同一个键可以关联多个值。在 std::unordered_multimap 中,元素的插入顺序是不确定的,并且不会因为元素的插入、删除或查找而改变。
std::unordered_multimap 与 std::multimap 的主要区别如下:
- std::multimap 也是一个关联容器,它存储的元素也是键值对,并且同样允许键的重复。但是,std::multimap 的内部实现是基于红黑树这种有序数据结构,因此它存储的元素是按键的升序(或降序,取决于比较函数的定义)排列的。而 std::unordered_multimap 则不保证元素的任何顺序,它主要关注的是高效的查找、插入和删除操作。
- 在性能上,std::unordered_multimap 的查找、插入和删除操作的时间复杂度通常接近 O(1),这是因为它使用了哈希表这种数据结构。而 std::multimap 的这些操作的时间复杂度则是 O(log n),因为它基于红黑树实现。因此,当对性能有较高要求,且不需要元素有序时,std::unordered_multimap 可能会是一个更好的选择。
std::unordered_multimap 的实现基于哈希表。哈希表是一种数据结构,它使用哈希函数将键映射到数组的索引,从而可以在常数时间内找到键对应的值。在 std::unordered_multimap 中,由于允许键的重复,所以每个哈希表槽位可能对应一个链表或其他动态数组结构,用于存储具有相同哈希值的键值对。
当插入一个元素时,首先计算键的哈希值,然后使用该哈希值找到数组中的对应槽位。如果槽位为空,则直接在该槽位插入新的键值对。如果槽位已有元素,则将新的键值对添加到对应的链表或动态数组中。
查找和删除操作也类似,首先计算键的哈希值找到对应的槽位,然后在槽位对应的链表或动态数组中查找或删除指定的键值对。
需要注意的是,哈希表的性能在很大程度上取决于哈希函数的质量。一个好的哈希函数应该能够将键均匀地映射到数组的各个槽位,以减少哈希冲突的发生。
2 声明与初始化
2.1 声明
首先,需要包含 <unordered_map> 头文件,然后声明一个 std::unordered_multimap 变量,并指定键和值的类型。
#include <unordered_map> std::unordered_multimap<KeyType, ValueType> mapName;
其中 KeyType 是键的类型,ValueType 是值的类型,mapName 是你为该 unordered_multimap 变量选择的名称。
2.2 初始化
初始化 std::unordered_multimap 可以通过多种方式进行,包括默认初始化、使用列表初始化器初始化、复制初始化、移动初始化等。
(1)默认初始化
如果没有提供任何初始化器,std::unordered_multimap 将被默认初始化,这意味着它将不包含任何元素,并且会使用默认的哈希函数和键相等性比较对象。
std::unordered_multimap<std::string, int> myMultimap; // 默认初始化
(2)使用列表初始化器初始化
可以使用列表初始化器(大括号 {})来初始化 std::unordered_multimap,并直接添加一些元素。
std::unordered_multimap<std::string, int> myMultimap = { {"apple", 1}, {"banana", 2}, {"apple", 3} // 注意:允许相同的键
};
在这个例子中,myMultimap 初始时包含三个元素,其中有两个元素具有相同的键 “apple”。
(3)注意事项
- std::unordered_multimap 不保证元素的顺序,因此不应该依赖特定的插入顺序。
- 插入到 std::unordered_multimap 中的键可以重复。
- 如果键类型没有提供默认的哈希函数和相等性比较对象,则需要提供自定义的实现(后面会详细讲解)。
3 插入元素
3.1 插入方法
(1)使用 insert 成员函数
std::unordered_multimap 提供了一个 insert 成员函数,用于向容器中插入元素。该函数接受一个键值对,并将其添加到容器中。如果容器中已经存在具有相同键的元素,insert 函数仍然会插入新的键值对,因为 std::unordered_multimap 允许键的重复。
插入单个键值对
可以使用 insert 函数插入单个键值对。这通常通过创建一个 std::pair 对象来实现,其中第一个元素是键,第二个元素是值。
#include <unordered_map>
#include <string> int main()
{ std::unordered_multimap<std::string, int> myMultimap; // 插入单个键值对 myMultimap.insert(std::make_pair("apple", 10)); // 也可以直接使用花括号初始化列表来构造 pair 对象 myMultimap.insert({"banana", 20}); return 0;
}
这个例子创建了一个 std::unordered_multimap 对象 myMultimap,并使用 insert 函数插入了两个键值对。第一个键值对是 (“apple”, 10),第二个键值对是 (“banana”, 20)。
插入多个键值对
也可以使用初始化列表一次性插入多个键值对。
#include <unordered_map>
#include <string> int main()
{ std::unordered_multimap<std::string, int> myMultimap; // 插入多个键值对 myMultimap.insert({ {"apple", 10}, {"banana", 20}, {"orange", 30} }); return 0;
}
在这个例子中,使用初始化列表一次性插入了三个键值对。
(2)使用迭代器插入
insert 函数还有一个重载版本,它接受一个迭代器和一个键值对,尝试在迭代器指向的位置插入元素。如果插入成功,函数返回一个指向新插入元素的迭代器;如果插入失败(例如,由于内存不足),则返回一个指向容器中下一个有效位置的迭代器。
#include <unordered_map>
#include <string> int main()
{ std::unordered_multimap<std::string, int> myMultimap; // 插入一个键值对,并获取指向它的迭代器 auto it = myMultimap.insert(myMultimap.begin(), std::make_pair("apple", 10)); return 0;
}
这个例子使用 insert 函数的迭代器版本在容器的开始位置尝试插入一个键值对。返回的迭代器 it 指向新插入的元素。
(3)使用 emplace 成员函数
除了 insert 函数外,std::unordered_multimap 还提供了 emplace 成员函数,它可以在容器内直接构造元素,避免了不必要的复制或移动操作。这对于大型对象或那些复制/移动成本较高的对象特别有用。
#include <unordered_map>
#include <string> struct LargeObject { std::string data; // ... 其他成员和数据 ... LargeObject(const std::string& d) : data(d) { // 构造函数实现 }
}; int main()
{ std::unordered_multimap<std::string, LargeObject> myMultimap; // 使用 emplace 插入元素,直接在容器内构造 LargeObject 对象 myMultimap.emplace("key", "large data"); return 0;
}
这个例子定义了一个名为 LargeObject 的结构,它有一个接受 std::string 的构造函数。我们使用 emplace 函数直接向 myMultimap 中插入一个 LargeObject 对象,避免了先构造对象再复制的额外开销。
3.2 注意事项
- 插入操作的时间复杂度在平均情况下是 O(1),但由于哈希冲突的存在,最坏情况下的时间复杂度可能较高。因此,为了获得最佳性能,应确保键的哈希函数分布均匀,并尽量减少哈希冲突。
- 插入操作可能会导致容器的重新哈希(rehashing),这是一个相对昂贵的操作,因为它涉及到重新分配内存和重新计算所有元素的哈希值。
4 访问元素
4.1 使用迭代器遍历元素
由于 std::unordered_multimap 是一种容器,因此可以使用迭代器来遍历并访问其中的元素。迭代器类似于指针,可以用来访问容器中的元素。
(1)遍历所有元素
可以使用 begin() 和 end() 成员函数来获取指向容器第一个元素和最后一个元素之后位置的迭代器,然后使用这些迭代器遍历容器中的所有元素。
#include <iostream>
#include <unordered_map>
#include <string> int main()
{ std::unordered_multimap<std::string, int> myMultimap = { {"apple", 10}, {"banana", 20}, {"apple", 30}, {"orange", 40} }; // 使用迭代器遍历所有元素 for (auto it = myMultimap.begin(); it != myMultimap.end(); ++it) { std::cout << it->first << ": " << it->second << std::endl; } return 0;
}
这个例子创建了一个 std::unordered_multimap 对象 myMultimap,并使用 begin() 和 end() 获取迭代器来遍历容器中的所有元素。it->first 访问键,it->second 访问值。
(2)遍历具有特定键的所有元素
由于 std::unordered_multimap 允许键的重复,可能需要遍历具有特定键的所有元素。这可以通过结合 equal_range 函数和迭代器来实现。
#include <iostream>
#include <unordered_map>
#include <string> int main() { std::unordered_multimap<std::string, int> myMultimap = { {"apple", 10}, {"banana", 20}, {"apple", 30}, {"orange", 40} }; // 查找键为 "apple" 的所有元素 auto range = myMultimap.equal_range("apple"); for (auto it = range.first; it != range.second; ++it) { std::cout << it->second << std::endl; // 输出值 } return 0;
}
上面代码的输出为:
10
30
在这个例子中,equal_range 返回一个包含两个迭代器的 pair,第一个迭代器指向第一个键为 “apple” 的元素,第二个迭代器指向第一个键不为 “apple” 的元素。通过遍历这个范围来访问所有键为 “apple” 的元素。
4.2 使用 find 函数查找元素
如果只需要查找具有特定键的第一个元素,可以使用 find 函数。如果找到了匹配的元素,find 会返回一个指向该元素的迭代器;如果没有找到,则返回 end() 迭代器。
#include <iostream>
#include <unordered_map>
#include <string> int main() { std::unordered_multimap<std::string, int> myMultimap = { {"apple", 10}, {"banana", 20}, {"apple", 30}, {"orange", 40} }; // 查找键为 "apple" 的第一个元素 auto it = myMultimap.find("apple"); if (it != myMultimap.end()) { std::cout << "Found apple with value: " << it->second << std::endl; } else { std::cout << "Apple not found." << std::endl; } return 0;
}
这个例子使用 find 函数来查找键为 “apple” 的第一个元素。如果找到了,就输出它的值;否则,输出 “Apple not found.”。
5 删除元素
5.1 使用 erase 成员函数删除单个元素
erase 成员函数可以用于删除容器中的单个元素。可以通过传递一个指向要删除元素的迭代器来调用它。
#include <iostream>
#include <unordered_map>
#include <string> int main() { std::unordered_multimap<std::string, int> myMultimap = { {"apple", 10}, {"banana", 20}, {"apple", 30}, {"orange", 40} }; // 假设我们有一个指向要删除元素的迭代器 auto it = myMultimap.find("apple"); // 查找键为 "apple" 的一个元素 if (it != myMultimap.end()) { // 使用 erase 删除找到的元素 myMultimap.erase(it); } // 输出容器内容以验证元素已被删除 for (const auto& pair : myMultimap) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0;
}
上面代码的输出为:
apple: 30
banana: 20
orange: 40
在这个例子中,首先使用 find 函数找到一个键为 “apple” 的元素的迭代器。然后,检查找到的迭代器是否不等于 end(),以确保找到了有效的元素。最后,调用 erase 并传入迭代器来删除该元素。
5.2 使用 erase 成员函数删除删除一系列元素
erase 成员函数还有一个重载版本,它接受两个迭代器作为参数,用于删除一个范围内的所有元素。这在你想要删除具有特定键的所有元素时非常有用。
#include <iostream>
#include <unordered_map>
#include <string> int main()
{ std::unordered_multimap<std::string, int> myMultimap = { {"apple", 10}, {"banana", 20}, {"apple", 30}, {"orange", 40} }; // 查找键为 "apple" 的元素范围 auto range = myMultimap.equal_range("apple"); // 删除范围内的所有元素 myMultimap.erase(range.first, range.second); // 输出容器内容以验证元素已被删除 for (const auto& pair : myMultimap) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0;
}
上面代码的输出为:
banana: 20
orange: 40
这个例子使用 equal_range 函数来获取一个包含所有键为 “apple” 的元素的范围。然后,调用 erase 并传入这个范围的开始和结束迭代器来删除所有这些元素。
5.3 使用 clear 成员函数删除所有元素
如果想要删除 std::unordered_multimap 中的所有元素,可以使用 clear 成员函数。这将移除容器中的所有键值对,并将容器的大小变为 0。
std::unordered_multimap<int, std::string> myMap;
// 假设 myMap 中已经填充了一些元素 myMap.clear(); // 删除所有元素,myMap 现在为空
5.4 遍历删除
在 std::unordered_multimap 中遍历并删除元素时,需要特别小心,因为删除操作会使指向已删除元素的迭代器失效。如果试图使用一个已经失效的迭代器,程序可能会崩溃或产生不可预测的行为。
一种常见的策略是使用迭代器从 begin() 到 end() 遍历容器,并在遍历过程中删除满足特定条件的元素。但是,由于直接删除当前迭代器指向的元素会使迭代器失效,需要在删除前获取下一个迭代器的位置。这可以通过递增当前迭代器来完成,然后在递增之前检查它是否指向要删除的元素。
以下是一个示例,展示如何在遍历 std::unordered_multimap 时删除所有键为 “apple” 的元素:
#include <iostream>
#include <unordered_map>
#include <string> int main()
{ std::unordered_multimap<std::string, int> myMultimap = { {"apple", 10}, {"banana", 20}, {"apple", 30}, {"orange", 40}, {"apple", 50} }; // 使用迭代器遍历并删除键为 "apple" 的所有元素 for (auto it = myMultimap.begin(); it != myMultimap.end(); ) { if (it->first == "apple") { // 删除元素,并使迭代器指向下一个有效元素 it = myMultimap.erase(it); } else { // 如果不删除,则递增迭代器 ++it; } } // 输出容器内容以验证元素已被删除 for (const auto& pair : myMultimap) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0;
}
上面代码的输出为:
banana: 20
orange: 40
这个例子使用了一个 for 循环来遍历 myMultimap。在循环内部,首先检查当前迭代器的键是否为 “apple”。如果是,则调用 erase 来删除该元素,并更新迭代器 it 为 erase 返回的下一个有效迭代器。如果不删除当前元素,就递增迭代器以继续遍历。
注意:erase 成员函数返回指向被删除元素之后的那个元素的迭代器。如果 erase 被调用在最后一个元素上,它将返回 end()。这就是为什么循环条件仍然是 it != myMultimap.end(),因为即使删除了当前元素,it 在更新后仍然可能不是 end()。
这种遍历并删除元素的方法在大多数情况下都是安全的,因为它避免了使用已经失效的迭代器。然而,如果容器在遍历过程中被其他线程修改,那么可能会出现数据竞争。在多线程环境中,应确保适当的同步机制来避免这种情况。
6 使用自定义键类型
std::unordered_multimap 也可以使用自定义键类型。当使用自定义键类型时,需要为该类型定义哈希函数和键相等性比较函数。哈希函数用于将键映射到哈希表中的位置,而键相等性比较函数则用于确定两个键是否相等。
下面是一个示例,展示了如何使用自定义键类型 Person 作为 std::unordered_multimap 的键:
#include <iostream>
#include <unordered_map>
#include <string>
#include <functional> // 用于 std::hash 和 std::equal_to // 自定义键类型
struct Person { Person(const std::string& name, int age) : name(name), age(age) {} // 为了简化示例,这里只根据name字段进行比较和哈希 bool operator==(const Person& other) const { return name == other.name; } std::string name; int age;
}; // 为Person定义哈希函数
struct PersonHash { std::size_t operator()(const Person& p) const { std::size_t h1 = std::hash<std::string>()(p.name); // 可以在这里添加更多字段的哈希计算,如果需要的话 return h1; }
}; // 为Person定义键相等性比较函数
struct PersonEqual { bool operator()(const Person& lhs, const Person& rhs) const { return lhs.name == rhs.name; }
}; int main()
{ // 使用自定义键类型的unordered_multimap std::unordered_multimap<Person, int, PersonHash, PersonEqual> peopleMap; // 插入元素 peopleMap.emplace(Person("Alice", 30), 1); peopleMap.emplace(Person("Bob", 25), 2); peopleMap.emplace(Person("Alice", 30), 3); // 相同的Person对象可以插入多次 // 遍历并打印元素 for (const auto& pair : peopleMap) { std::cout << pair.first.name << ": " << pair.first.age << " -> " << pair.second << std::endl; } return 0;
}
上面代码的输出为:
Alice: 30 -> 1
Alice: 30 -> 3
Bob: 25 -> 2
这个例子定义了一个 Person 结构体,它包含 name 和 age 两个字段。此外还为 Person 定义了哈希函数 PersonHash 和键相等性比较函数 PersonEqual。
在创建 std::unordered_multimap 时,将 Person 作为键类型,并将 PersonHash 和 PersonEqual 作为模板参数传递给 std::unordered_multimap。这样,unordered_multimap 就知道如何为 Person 对象计算哈希值以及如何比较两个 Person 对象是否相等。
注意:在哈希函数和键相等性比较函数中,只考虑了 Person 的 name 字段。在实际情况中,可能需要根据 Person 的所有字段来计算哈希值和比较相等性,以确保正确的行为。特别是当两个 Person 对象具有相同的 name 但不同的 age 时,只根据 name 进行哈希和比较可能会导致意外的行为。
相关文章:
突破编程_C++_C++11新特性(unordered_multimap)
1 概述 std::unordered_multimap 是一个哈希表实现的无序容器,它存储的元素是键值对,并且允许键的重复。这意味着同一个键可以关联多个值。在 std::unordered_multimap 中,元素的插入顺序是不确定的,并且不会因为元素的插入、删除…...

15.WEB渗透测试--Kali Linux(三)
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于: 易锦网校会员专享课 上一个内容:14.WEB渗透测试--Kali Linux(二)-CSDN博客 Kali工具使用 3389远…...
Android-Framework pm list packages和pm install返回指定应用信息
一、环境 高通 Android 13 注:Android10 和Android13有些差异,代码位置不变,参照修改即可 二、pm简单介绍 pm工具为包管理(package manager)的简称 可以使用pm工具来执行应用的安装和查询应用宝的信息、系统权限、…...

CSS
什么是CSS? CSS是一门语言,用于控制网页表现 CSS(Cascading Style Sheet):层叠样式表 W3C标准:网页主要由三部分组成 结构:HTML表现:CSS行为:JavaScript CSS导入方式…...

算法详解——选择排序和冒泡排序
一、选择排序 选择排序算法的执行过程是这样的:首先,算法遍历整个列表以确定最小的元素,接着,这个最小的元素被置换到列表的开头,确保它被放置在其应有的有序位置上。接下来,从列表的第二个元素开始&#x…...

图论(蓝桥杯 C++ 题目 代码 注解)
目录 迪杰斯特拉模板(用来求一个点出发到其它点的最短距离): 克鲁斯卡尔模板(用来求最小生成树): 题目一(蓝桥王国): 题目二(随机数据下的最短路径&#…...

矩阵起源新一年喜报连连!
新春伊始 矩阵起源向大家分享 一连串好消息 首先,公司创始人兼CEO王龙先生获评“2023深圳创新突出贡献人物“。这一荣誉是对其在推动数据库行业技术创新和产品开发方面所做出的卓越贡献的认可。他的领导力和创新精神不仅引领我司取得了显著的成就,也为…...

牛客——紫魔法师(并查集)
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 “サーヴァント、キャスター、Medea。”--紫魔法师 给出一棵仙人掌(每条边最多被包含于一个环,无自环,无重边,保证连通),要求用最少的…...

最新WooCommerce教程指南-如何搭建B2C外贸独立站
WooCommerce是全球最受欢迎的开源电子商务平台之一。它基于WordPress建站,只需一键安装即可使用。该平台提供了丰富的功能,包括产品发布、库存管理、支付网关和运输发货等,可以帮助搭建各种类型的电子商务网站。相比其他竞争对手,…...

一文教会你SpringBoot是如何启动的
SpringBoot启动流程分析 流程图 源码剖析 运行Application.run()方法 我们在创建好一个 SpringBoot 程序之后,肯定会包含一个类:xxxApplication,我们也是通过这个类来启动我们的程序的(梦开始的地方),而…...

车载测试面试:各大车企面试题汇总
本博主可协助大家成功进军车载测试行业 TBOX 深圳 涉及过T-BOX测试吗Ota升级涉及的台架环境是什么样的?上车实测之前有没有一个仿真环境台架环境都什么零部件T-BOX了解多少Linux和shell有接触吗 单片机uds诊断是在实车上座的吗 uds在实车上插的那口 诊断仪器是哪…...
Qt散文一
Qt的事件分为普通事件和系统事件,普通事件比如用户按下键盘,系统事件比如定时器事件。事件循环的开始是从main函数的QApplication,然后调用exec()开始的,在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件…...

MySQL学习Day32——数据库备份与恢复
在任何数据库环境中,总会有不确定的意外情况发生,比如例外的停电、计算机系统中的各种软硬件故障、人为破坏、管理员误操作等是不可避免的,这些情况可能会导致数据的丢失、 服务器瘫痪等严重的后果。存在多个服务器时,会出现主从服…...

阅读基础知识
一 网络 1. 三次握手四次挥手 三次握手:为了建立长链接进行交互即建立一个会话,使用 http/https 协议 ① 客户端产生初始化序列号 Seqx ,向服务端发送建立连接的请求报文,将 SYN1 同步序列号; ② 服务端接收建立连接…...
【NestJS 编程艺术】1. NestJS设计模式深度解析:构建高效、可维护的服务端应用
在当今快速发展的软件开发领域,Node.js凭借其轻量级和高性能的特点,已经成为了构建服务端应用的首选技术之一。然而,随着应用规模的扩大,传统的Node.js框架如Express和Koa可能在架构设计和代码组织上显得力不从心。这时࿰…...
QT中connect()的参数5:Qt::DirectConnection、Qt::QueuedConnection区别
原文链接:https://blog.csdn.net/Dasis/article/details/120916993 connect用于连接QT的信号和槽,在qt编程过程中不可或缺。它其实有第5个参数,只是一般使用默认值,在满足某些特殊需求的时候可能需要手动设置。 Qt::AutoConnect…...

VXLAN学习笔记
声明:该博客内容大部分参考参考链接整理 什么是VXLAN? VXLAN(Virtual Extensible LAN)即虚拟扩展局域网,是大二层网络中广泛使用的网络虚拟化技术。在源网络设备与目的网络设备之间建立一条逻辑VXLAN隧道,采用MAC in UDP的封装方…...

全排列的不同写法(茴字的不同写法)及对应的时间开销
资源课件: CS106B-recursion-pptstanford library-timer.hstanford library-set.h 不同的方法 1------ Set<string> permutations1Rec(string remaining) {Set<string> res;if(remaining.size() 0) {res "";}else {for(int i 0; i <…...
权衡后台数据库设计中是否使用外键
目录 引言 外键简介 对比 真实后台项目中的权衡 结论 引言 在大学学习数据库课程时,我们会早早的接触到外键这一概念,同时我相信大部分人在懂了外键的概念后都会觉得外键很重要,在涉及多表一定要用,但后来在我接触到真实项目…...

ChatGPT提示词方法的原理
关于提示词,我之前的一些文章可以参考: 【AIGC】AI作图最全提示词prompt集合(收藏级)https://giszz.blog.csdn.net/article/details/134815245?ydrefereraHR0cHM6Ly9tcC5jc2RuLm5ldC9tcF9ibG9nL21hbmFnZS9hcnRpY2xlP3NwbT0xMDExL…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...