【C++】unordered系列容器
1、unordered容器介绍
unordered容器是C++标准库中提供的一组无序关联式容器,用于存储和管理无序的数据集合。这些容器的特点是快速的查找、插入和删除操作,其内部实现通常基于哈希表(hash table)。
C++标准库提供了四种unordered容器:
- unordered_set:无序唯一元素集合,存储一组唯一的元素,不允许重复。
- unordered_multiset:无序元素集合,存储一组元素,允许重复。
- unordered_map:无序键值对集合,存储一组唯一的键值对,每个键只能出现一次。
- unordered_multimap:无序键值对集合,存储一组键值对,允许键的重复。
这些容器的特点如下:
-
无序性:unordered容器中的元素没有特定的顺序,与插入的顺序无关。元素的存储位置是根据其哈希值来确定的,而不是根据比较操作符。这使得无序容器在查找操作上具有常数时间复杂度,而有序容器通常需要对元素进行排序和比较。
-
哈希表实现:unordered容器内部通常使用哈希表实现。哈希表是一种将元素的键映射到存储位置的数据结构,通过使用哈希函数将键转换为存储桶的索引。这样可以在平均情况下实现常数时间的插入、查找和删除操作。
-
高效的插入和删除:由于无序容器使用哈希表,插入和删除操作的时间复杂度通常是常数时间。这使得无序容器特别适用于需要频繁插入和删除元素的场景。
-
自定义键类型:无序容器支持使用自定义类型作为键。为了支持自定义类型,需要提供自定义的哈希函数和相等比较函数。
使用unordered容器的步骤如下:
-
包含头文件:在使用unordered容器之前,需要包含
<unordered_set>
,<unordered_map>
头文件,并使用适当的命名空间(例如std
)。 -
创建容器对象:使用容器的类型名称和模板参数,声明一个容器对象。
-
插入和访问元素:使用容器的成员函数来插入和访问元素。
-
查找和删除元素:使用成员函数进行元素的查找和删除操作。
无序容器还提供了许多其他的成员函数和操作,如 size()
返回容器中的元素数量,clear()
清空容器等。具体的使用方法和注意事项可以在C++标准库的文档中找到。
2、unordered_map
2.1 介绍
-
unordered_map是一种关联式容器,用于存储键值对(key-value pair)。通过键(key),可以快速地索引到与之关联的值(value)。
-
在unordered_map中,键用于唯一地标识元素,而映射值则是与键相关联的对象。键和映射值的类型可以不同。
-
unordered_map内部使用哈希表(hash table)实现,相同哈希值的键值对被放置在相同的桶中。它并不对键值对按任何特定顺序进行排序,而是根据哈希值来组织元素。
-
由于unordered_map的内部实现是基于哈希表,通过键进行单个元素的访问速度比有序容器(如map)要快。然而,当需要遍历元素子集时,unordered_map的效率可能较低,因为元素的顺序是无序的。
-
unordered_map实现了直接访问操作符(operator[]),允许使用键作为参数直接访问对应的值。例如:
value = myMap[key];
-
unordered_map的迭代器至少是前向迭代器,可以用于遍历容器中的元素。可以使用迭代器来访问键值对、进行插入、删除等操作。
2.2 接口说明以及使用
2.2.1 构造
unordered_map提供了多种构造函数,可以根据不同的需求进行初始化。以下是一些常用的构造函数及其使用示例:
-
默认构造函数:
std::unordered_map<Key, T> myMap;
示例:
std::unordered_map<std::string, int> myMap; // 创建一个空的unordered_map
-
初始化列表构造函数:
std::unordered_map<Key, T> myMap = {{key1, value1}, {key2, value2}, ...};
示例:
std::unordered_map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; // 创建并初始化一个unordered_map
-
范围构造函数:
template <typename InputIt> std::unordered_map<Key, T> myMap(InputIt first, InputIt last);
示例:
std::vector<std::pair<std::string, int>> data = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; std::unordered_map<std::string, int> myMap(data.begin(), data.end()); // 通过范围构造函数创建unordered_map
-
拷贝构造函数:
std::unordered_map<Key, T> myMap(otherMap);
示例:
std::unordered_map<std::string, int> myMap(otherMap); // 通过拷贝构造函数创建unordered_map
-
移动构造函数:
std::unordered_map<Key, T> myMap(std::move(otherMap));
示例:
std::unordered_map<std::string, int> myMap(std::move(otherMap)); // 通过移动构造函数创建unordered_map
在上述示例中,“Key” 表示unordered_map中的键类型,“T” 表示unordered_map中的值类型。
2.2.2 容量函数
在unordered_map中,您可以使用以下两个成员函数来查询容器的状态和大小:
-
empty():此函数用于检查unordered_map是否为空。如果容器为空,返回true;否则,返回false。
bool empty() const;
示例:
std::unordered_map<std::string, int> myMap; if (myMap.empty()) { std::cout << "myMap is empty." << std::endl; }
-
size():此函数返回unordered_map中存储的键值对数量。
size_t size() const;
示例:
std::unordered_map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; size_t mapSize = myMap.size(); std::cout << "myMap size: " << mapSize << std::endl;
这些函数可以了解unordered_map的当前状态和大小。可以根据需要使用它们来编写相关的逻辑或进行容器的控制流程。
上述示例中的std::unordered_map<std::string, int>
可以根据实际的键和值类型进行调整。
2.2.3 迭代器
在unordered_map中,可以使用以下四个成员函数来获取迭代器以遍历容器中的元素:
-
begin():返回指向unordered_map中第一个元素的迭代器。
iterator begin();
示例:
std::unordered_map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; auto it = myMap.begin(); // 获取指向第一个元素的迭代器
-
end():返回指向unordered_map中最后一个元素之后位置的迭代器。
iterator end();
示例:
std::unordered_map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; auto it = myMap.end(); // 获取指向最后一个元素之后位置的迭代器
-
cbegin():返回指向unordered_map中第一个元素的const迭代器。
const_iterator cbegin() const;
示例:
const std::unordered_map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; auto it = myMap.cbegin(); // 获取指向第一个元素的const迭代器
-
cend():返回指向unordered_map中最后一个元素之后位置的const迭代器。
const_iterator cend() const;
示例:
const std::unordered_map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; auto it = myMap.cend(); // 获取指向最后一个元素之后位置的const迭代器
使用这些函数可以获取迭代器,然后可以使用迭代器来遍历unordered_map中的键值对,进行插入、删除或其他操作。
上述示例中的std::unordered_map<std::string, int>
可以根据实际的键和值类型进行调整。
2.2.4 修改操作
在unordered_map中,可以使用以下几个成员函数来插入、删除、清空和交换容器中的元素:
-
insert():插入一个键值对或一组键值对到unordered_map中。
std::pair<iterator, bool> insert(const value_type& value); iterator insert(const_iterator hint, const value_type& value); template <typename InputIt> void insert(InputIt first, InputIt last);
示例:
std::unordered_map<std::string, int> myMap; // 插入单个键值对 myMap.insert(std::make_pair("apple", 5)); // 插入一组键值对 std::vector<std::pair<std::string, int>> data = {{"banana", 3}, {"orange", 2}}; myMap.insert(data.begin(), data.end());
-
erase():从unordered_map中删除一个或一组键值对。
iterator erase(iterator pos); size_type erase(const key_type& key); iterator erase(const_iterator first, const_iterator last);
示例:
std::unordered_map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; // 删除单个键值对 myMap.erase("apple"); // 删除一组键值对 auto it = myMap.find("banana"); if (it != myMap.end()) { myMap.erase(it, myMap.end()); }
-
clear():清空unordered_map中的所有键值对,使其成为空容器。
void clear();
示例:
std::unordered_map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; myMap.clear(); // 清空unordered_map
-
swap():交换两个unordered_map的内容,使其互相交换。
void swap(unordered_map& other);
示例:
std::unordered_map<std::string, int> myMap1 = {{"apple", 5}}; std::unordered_map<std::string, int> myMap2 = {{"banana", 3}, {"orange", 2}}; myMap1.swap(myMap2); // 交换两个unordered_map的内容
这些函数可用于对unordered_map进行插入、删除、清空和交换操作。请根据实际需求选择适当的函数进行操作。
上述示例中的std::unordered_map<std::string, int>
可以根据实际的键和值类型进行调整。
2.2.5 查找操作
在unordered_map中,可以使用以下两个成员函数来查找键和计算特定键的数量:
-
find():查找给定键在unordered_map中的位置,并返回一个指向该位置的迭代器。
iterator find(const key_type& key); const_iterator find(const key_type& key) const;
示例:
std::unordered_map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; auto it = myMap.find("apple"); if (it != myMap.end()) { // 键 "apple" 存在于unordered_map中 std::cout << "Value: " << it->second << std::endl; }
-
count():计算特定键在unordered_map中的数量,并返回该数量。
size_type count(const key_type& key) const;
示例:
std::unordered_map<std::string, int> myMap = {{"apple", 5}, {"banana", 3}, {"orange", 2}}; if (myMap.count("apple") > 0) { // 键 "apple" 存在于unordered_map中 std::cout << "Key 'apple' found." << std::endl; }
请注意,find() 函数返回一个迭代器,指向unordered_map中键为给定键的元素。如果元素不存在,则返回unordered_map的end()迭代器。
count() 函数返回给定键在unordered_map中的数量。由于unordered_map的键是唯一的,返回值只能是0或1。
上述示例中的std::unordered_map<std::string, int>
可以根据实际的键和值类型进行调整。
2.2.6 桶操作
在关联式容器(包括unordered_map)中,桶(bucket)是容器内部的一个存储区域,用于存放元素。桶操作是指对这些存储桶进行访问和操作的功能。
unordered_map内部使用哈希表(hash table)来组织和存储元素。哈希表根据键的哈希值将元素映射到特定的存储桶中。每个存储桶可以包含零个或多个元素。桶操作允许直接访问和操作这些存储桶,以便更好地了解和控制unordered_map的内部结构和性能。
以下是一些常见的桶操作:
-
bucket_count():返回unordered_map中的存储桶的数量。
size_type bucket_count() const;
-
bucket_size():返回特定存储桶中的元素数量。
size_type bucket_size(size_type n) const;
-
bucket():返回给定键的元素所在的存储桶的索引。
size_type bucket(const key_type& key) const;
-
begin(bucket_index):返回指向特定存储桶中第一个元素的迭代器。
local_iterator begin(size_type n);
-
end(bucket_index):返回指向特定存储桶中最后一个元素之后位置的迭代器。
local_iterator end(size_type n);
通过这些桶操作可以了解unordered_map中存储桶的数量、每个存储桶中的元素数量,以及特定键所在的存储桶索引。还可以使用迭代器来遍历特定存储桶中的元素。
这些桶操作是unordered_map的特定成员函数,用于提供对存储桶的访问和操作功能。
3、unordered_set
具体接口函数可以自行查找
这里说明它与unordered_map间的异同点:
unordered_map和unordered_set是C++标准库中提供的两种容器,它们有以下相同点和不同点:
相同点:
底层实现:unordered_map和unordered_set都是基于哈希表(hash table)实现的,利用哈希函数将元素映射到存储桶中,以实现高效的插入、查找和删除操作。
查找效率:无论是unordered_map还是unordered_set,都具有快速的查找效率。由于哈希表的特性,平均情况下,它们的查找操作的时间复杂度为常数。
迭代器:unordered_map和unordered_set都提供了迭代器(iterator),可以用于遍历容器中的元素。
自定义键类型:两者都支持使用自定义类型作为键。需要提供自定义的哈希函数和相等比较函数来支持自定义键类型。
不同点:
存储方式:unordered_map存储键值对(key-value pair),而unordered_set只存储唯一的值(value)。unordered_map使用键来唯一标识和访问每个元素,而unordered_set仅依靠值来唯一标识每个元素。
元素类型:unordered_map中的元素是键值对,其中键和值的类型可以不同。而unordered_set中的元素只包含值,类型由模板参数指定。
存储结构:由于unordered_map存储键值对,因此它的存储结构相对于unordered_set要复杂一些。unordered_map中的每个存储桶都存储了一个键值对,而unordered_set中的每个存储桶只存储一个值。
插入操作:在unordered_map中,插入一个新的键值对时,需要同时提供键和值。而在unordered_set中,插入一个新值只需要提供该值即可。文章来源:https://www.toymoban.com/news/detail-564619.html
总体上,unordered_map适用于需要存储键值对的情况,可以通过键快速访问对应的值;而unordered_set适用于只需存储独特值的情况,可以快速判断某个值是否存在。文章来源地址https://www.toymoban.com/news/detail-564619.html
到了这里,关于【C++】unordered系列容器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!