一.map
1.1map概念
简介:
- map中一切元素都是pair
- pair中第一个元素为key(键值),起到索引效果,第二个元素为value(实值)
- 一切元素都会依据元素的键值主动排序
本质:
- . map/multimap归于相关式容器,底层结构是用二叉树完成。
长处:
- 能够依据key值快速找到value值
map和multimap差异:
-
map不答应容器中有重复key值元素
-
multimap答应容器中有重复key值元素
1.2pair模板类
效果
std::pair
是 C++ 标准库中界说的一个模板类,用于将两个值组合为一个类型。它供给了简单的方法来存储和操作两个不同类型的值。
以下是 std::pair
的一些特色和用法:
-
创立
pair
目标:- 运用结构函数,能够指定两个值。
-
拜访
pair
目标的值:- 经过
first
和second
成员变量,别离拜访第一个和第二个值。
- 经过
-
比较
pair
目标:- 支持
==
、!=
、<
、<=
、>
、>=
运算符的比较操作。
- 支持
-
作为函数的回来值:
-
pair
能够用作函数的回来值,这样能够方便地回来多个值。
-
-
作为容器的元素:
-
pair
能够作为容器(如vector
、map
等)的元素,以存储多个不同类型的值。
-
例如,以下是运用 std::pair
的一个示例:
#include <iostream>
#include <utility>
int main() {
std::pair<int, std::string> myPair(1, "Hello");
std::cout << myPair.first << " " << myPair.second << std::endl;
return 0;
}
上述代码创立了一个 pair
目标 myPair
,其间第一个值为 1
,第二个值为 "Hello"
。在输出时,能够运用 first
和 second
成员变量来拜访这两个值,并输出结果为 1 Hello
。
std::pair
在许多情况下都非常有用,特别是当需求将两个不同类型的值作为一个实体运用时。
创立方法
std::pair
能够经过多种方法进行创立,以下是几种常见的创立方法:
-
运用结构函数:
- 运用带有参数的结构函数来创立
pair
目标,需求指定两个值的类型。
std::pair<int, std::string> myPair(1, "Hello");
- 运用带有参数的结构函数来创立
-
运用
std::make_pair()
函数:- 运用
std::make_pair()
函数能够更方便地创立pair
目标,不需求显式指定类型。
auto myPair = std::make_pair(1, "Hello");
- 运用
-
运用初始化列表:
- 能够运用初始化列表来创立
pair
目标,并指定两个值。
std::pair<int, std::string> myPair = {1, "Hello"};
- 能够运用初始化列表来创立
-
将
pair
作为函数的回来值:-
pair
能够作为函数的回来值,将多个值一起回来。
std::pair<int, std::string> getValues() { return std::make_pair(1, "Hello"); }
-
上述示例中,创立了一个 pair
目标,并指定了两个值。能够依据需求挑选合适的方法来创立 pair
目标。不管运用哪种方法,pair
都能够方便地将两个不同类型的值组合为一个目标。
创立方法 | 示例代码 |
---|---|
结构函数 | std::pair<int, std::string> myPair(1, "Hello"); |
std::make_pair() |
auto myPair = std::make_pair(1, "Hello"); |
初始化列表 | std::pair<int, std::string> myPair = {1, "Hello"}; |
作为函数回来值 | std::pair<int, std::string> getValues() { return std::make_pair(1, "Hello"); } |
1.3map的结构和赋值
map数据类型只能是各种pair
-
默许结构函数:
- 运用默许结构函数创立一个空的
map
容器。
std::map<KeyType, ValueType> myMap;
- 运用默许结构函数创立一个空的
-
初始化列表结构函数:
- 运用初始化列表结构函数,能够在创立
map
的同时初始化一些键-值对。
std::map<KeyType, ValueType> myMap = { {key1, value1}, {key2, value2}, ... };
- 运用初始化列表结构函数,能够在创立
-
规模结构函数:
- 运用另一个容器的规模结构函数,能够将其他容器的内容仿制到一个新的
map
中。
std::map<KeyType, ValueType> myMap(otherContainer.begin(), otherContainer.end());
- 运用另一个容器的规模结构函数,能够将其他容器的内容仿制到一个新的
-
仿制结构函数:
- 运用另一个
map
的仿制结构函数,能够创立一个已有map
的副本。
std::map<KeyType, ValueType> myMap(otherMap);
- 运用另一个
-
赋值运算符:
- 运用赋值运算符,将一个
map
的内容赋值给另一个map
。
std::map<KeyType, ValueType> myMap; myMap = otherMap;
- 运用赋值运算符,将一个
-
移动结构函数和移动赋值运算符:
- C++11 引入了移动语义,能够运用移动结构函数和移动赋值运算符来高效地将一个
map
的内容移动到另一个map
中,防止不必要的仿制。
std::map<KeyType, ValueType> myMap(std::move(otherMap)); // 移动结构函数 myMap = std::move(otherMap); // 移动赋值运算符
- C++11 引入了移动语义,能够运用移动结构函数和移动赋值运算符来高效地将一个
这些是运用 map
的常见结构和赋值方法。依据实践需求,挑选恰当的方法来结构和赋值 map
目标。
结构/赋值方法 | 示例代码 |
---|---|
默许结构函数 | std::map<KeyType, ValueType> myMap; |
初始化列表结构函数 | std::map<KeyType, ValueType> myMap = { {key1, value1}, {key2, value2}, ... }; |
规模结构函数 | std::map<KeyType, ValueType> myMap(otherContainer.begin(), otherContainer.end()); |
仿制结构函数 | std::map<KeyType, ValueType> myMap(otherMap); |
赋值运算符 | std::map<KeyType, ValueType> myMap; myMap = otherMap; |
移动结构函数 | std::map<KeyType, ValueType> myMap(std::move(otherMap)); |
移动赋值运算符 | myMap = std::move(otherMap); |
1.4map的巨细和交流
在C++中,std::map
供给了几种常用的成员函数来获取巨细以及进行交流操作。
-
获取巨细:
-
size()
函数能够回来当前map
中键值对的数量。
std::map<KeyType, ValueType> myMap; int size = myMap.size();
-
-
判别是否为空:
-
empty()
函数能够判别map
是否为空,回来一个布尔值表明是否为空。
std::map<KeyType, ValueType> myMap; bool isEmpty = myMap.empty();
-
-
交流 map:
-
swap()
函数能够交流两个map
容器的内容。
std::map<KeyType, ValueType> map1; std::map<KeyType, ValueType> map2; // 交流 map1 和 map2 的内容 map1.swap(map2);
-
运用这些操作能够方便地获取 map
的巨细,而且在需求时交流 map
容器的内容。记住,在交流时,map
中的元素会被交流,而且两个 map
的键值对会相互替换。
操作 | 示例代码 |
---|---|
获取巨细 |
std::map<KeyType, ValueType> myMap; int size = myMap.size();
|
判别是否为空 |
std::map<KeyType, ValueType> myMap; bool isEmpty = myMap.empty();
|
交流 map
|
std::map<KeyType, ValueType> map1; std::map<KeyType, ValueType> map2; map1.swap(map2);
|
1.5map的刺进和删去
在 C++ 中,std::map
供给了几种用于刺进和删去元素的成员函数和操作符。
-
刺进元素:
- 运用
insert()
函数能够刺进一个键值对或一对迭代器规模的键值对。
std::map<KeyType, ValueType> myMap; // 单个刺进 myMap.insert(std::make_pair(key, value)); // 刺进多个元素 std::map<KeyType, ValueType> anotherMap; myMap.insert(anotherMap.begin(), anotherMap.end());
- 运用
-
删去元素:
- 运用
erase()
函数能够删去指定键的元素,也能够运用迭代器来删去一个或一段元素。
std::map<KeyType, ValueType> myMap; // 删去指定键的元素 myMap.erase(key); // 删去迭代器指向的元素 std::map<KeyType, ValueType>::iterator it = myMap.find(key); if (it != myMap.end()) { myMap.erase(it); } // 删去元素规模 myMap.erase(myMap.begin(), myMap.end());
- 运用
-
清空 map:
- 运用
clear()
函数能够清空整个map
容器中的一切元素。
std::map<KeyType, ValueType> myMap; myMap.clear();
- 运用
这些是 std::map
刺进和删去元素的常见操作。依据实践需求,挑选恰当的方法来刺进和删去 map
中的元素。
操作 | 示例代码 |
---|---|
刺进单个元素 |
std::map<KeyType, ValueType> myMap; myMap.insert(std::make_pair(key, value));
|
刺进多个元素 |
std::map<KeyType, ValueType> myMap; std::map<KeyType, ValueType> anotherMap; myMap.insert(anotherMap.begin(), anotherMap.end());
|
删去指定键的元素 |
std::map<KeyType, ValueType> myMap; myMap.erase(key);
|
删去迭代器指向的元素 |
std::map<KeyType, ValueType> myMap; std::map<KeyType, ValueType>::iterator it = myMap.find(key); if (it != myMap.end()) { myMap.erase(it); }
|
删去元素规模 |
std::map<KeyType, ValueType> myMap; myMap.erase(myMap.begin(), myMap.end());
|
清空 map |
std::map<KeyType, ValueType> myMap; myMap.clear();
|
1.6map的查找和计算
在 C++ 中,std::set
供给了几种用于查找和计算元素的成员函数。
-
查找元素:
- 运用
find()
函数来查找指定值的元素,假如找到则回来指向该元素的迭代器,不然回来end()
迭代器。
std::set<ValueType> mySet; // 查找指定值的元素 std::set<ValueType>::iterator it = mySet.find(value); if (it != mySet.end()) { // 元素找到 }
- 运用
-
计算元素个数:
- 运用
count()
函数来计算指定值的元素在set
中呈现的次数。
std::set<ValueType> mySet; // 计算指定值的元素个数 int count = mySet.count(value);
- 运用
-
判别元素是否存在:
- 运用
count()
函数来判别指定值的元素是否存在于set
中(存在时回来 1 个或更多的计数)。
std::set<ValueType> mySet; // 判别指定值的元素是否存在 bool exists = mySet.count(value) > 0;
- 运用
这些是 std::set
查找和计算元素的常见操作。你能够依据实践需求,运用这些函数来查找特定的元素并计算元素的个数。
操作 | 示例代码 |
---|---|
查找指定值的元素 |
std::set<ValueType> mySet; std::set<ValueType>::iterator it = mySet.find(value); if (it != mySet.end()) { /* 元素找到 */ }
|
计算指定值的个数 |
std::set<ValueType> mySet; int count = mySet.count(value);
|
判别元素是否存在 |
std::set<ValueType> mySet; bool exists = mySet.count(value) > 0;
|
这个表格将 set
的查找和计算操作整理成了一个简练的表格。你能够依据实践需求运用这些操作来查找指定值的元素、获取指定值在调集中的个数,或者判别元素是否存在于调集中。
1.7map容器排序
map容器排序,和set排序一样,都需求借用仿函数。
在 C++ 中,std::map
是一个相关容器,依照键的主动排序进行存储。默许情况下,std::map
运用键的升序进行排序。但假如你期望依照其他方法进行排序,能够经过自界说比较函数来完成。
以下是一些完成 std::map
容器排序的示例代码:
#include <iostream>
#include <map>
#include <functional>
// 自界说比较函数,依照值的降序进行排序
struct CompareByValue {
bool operator()(const int& a, const int& b) const {
return a > b; // 运用大于号完成降序
}
};
int main() {
std::map<int, std::string> myMap; // 默许依照键的升序排序
// 增加元素
myMap.insert(std::make_pair(3, "C"));
myMap.insert(std::make_pair(1, "A"));
myMap.insert(std::make_pair(2, "B"));
// 遍历输出,默许依照键的升序输出
std::cout << "默许升序排序:" << std::endl;
for (const auto& pair : myMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
// 运用自界说比较函数,依照值的降序排序
std::map<int, std::string, CompareByValue> sortedMap;
// 仿制原始 map 的元素到排序后的 map
sortedMap.insert(myMap.begin(), myMap.end());
// 遍历输出,依照值的降序输出
std::cout << "按值降序排序:" << std::endl;
for (const auto& pair : sortedMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
在示例代码中,CompareByValue
结构体是一个自界说的比较函数目标,完成了依照值的降序进行排序。在创立 std::map
容器时,能够传入 CompareByValue
类型作为第三个模板参数来指定自界说比较函数。
注:假如你想对 std::map
进行临时排序而不影响原始数据的排序,你能够运用 std::multimap
或在仿制数据后进行排序。
二.multimap
multimap是键值能够重复的map。
std::map
和 std::multimap
之间的差异:
-
仅有性:
std::map
要求键的仅有性,每个键只能对应一个值。而std::multimap
答应键的重复,即能够存储多个具有相同键的值。 -
排序:
std::map
依照键的默许严厉弱序进行排序,这有助于提高搜索功率。默许情况下,键是依照升序排序的。而std::multimap
也依照键的默许严厉弱序进行排序,即也是依照升序排序的。 -
删去:关于
std::map
,删去给定键的元素将删去具有该键的仅有元素。而关于std::multimap
,删去给定键的元素将删去一切具有该键的元素。 -
multimap没有重载[ ],map能够直接用[]拜访,修正,刺进数据。
总结起来,std::map
合适存储仅有键值对并依照键进行排序的场景。而 std::multimap
合适存储答应键重复的键值对,而且也能够依照键进行排序。
三.unordered_map
在函数接口方面,std::map
和 std::unordered_map
之间有一些差异和差异。以下是其间的一些首要差异:
-
刺进元素:关于
std::map
,能够运用insert()
函数或[]
运算符刺进一个键值对。假如现已存在相同的键,则刺进不会生效。而关于std::unordered_map
,也能够运用insert()
函数或[]
运算符刺进一个键值对,但假如现已存在相同的键,则新的值将取代旧的值。 -
查找元素:关于
std::map
,能够运用find()
函数依据键查找元素,并回来一个迭代器指向找到的元素,假如没找到则回来末尾迭代器。而关于std::unordered_map
,也能够运用find()
函数依据键查找元素,回来一个迭代器指向找到的元素,假如没找到则回来和end()
持平的迭代器。 -
拜访元素:关于
std::map
,能够运用[]
运算符依据键拜访元素的值。而关于std::unordered_map
,同样能够运用[]
运算符依据键拜访元素的值。 -
删去元素:关于
std::map
,能够运用erase()
函数删去给定键的元素,假如存在多个具有相同键的元素,只会删去第一个匹配的元素。而关于std::unordered_map
,能够运用erase()
函数删去给定键的元素,它会删去一切具有相同键的元素。
除了上述不同之外,其他函数接口如迭代器操作、巨细操作、铲除容器等方面在 std::map
和 std::unordered_map
中基本上是相似的。
四.unordered_multimap
std::map
和 std::unordered_map
是两个不同的相关容器,而 std::unordered_multimap
则是 std::unordered_map
的多重键版本。下面是 std::unordered_multimap
和 std::map
的一些首要差异:
-
答应重复键:在
std::map
中,每个键只能对应仅有的值,假如刺进具有相同键的元素,则会替换旧值。但是,在std::unordered_multimap
中,能够刺进具有相同键的多个元素,而且答应重复键的存在。 -
元素次序:
std::map
是有序相关容器,它依照键的严厉弱次序进行排序。在遍历std::map
时,元素将依照排序次序拜访。而std::unordered_multimap
是无序相关容器,它不保证元素的次序,元素的存储和拜访次序可能会有所不同。 -
查找功率:由于
std::unordered_multimap
根据哈希表完成,查找操作的均匀时刻复杂度接近 O(1),而std::map
则是根据红黑树,查找操作的均匀时刻复杂度为 O(log n)。 -
刺进次序:在
std::map
中,每个元素依照键的次序进行刺进。而在std::unordered_multimap
中,元素的刺进次序与它们的哈希值相关,哈希值不一样的元素可能会以不同的次序刺进。
依据需求,挑选运用 std::map
、std::unordered_map
还是 std::unordered_multimap
取决于数据结构的要求和功能考虑。假如需求有序拜访和仅有键,能够挑选 std::map
;假如需求快速查找,而且键能够重复,能够挑选 std::unordered_multimap
。