当前位置:   article > 正文

【C++关联式容器】unordered_set

【C++关联式容器】unordered_set

目录

unordered_set

1. 关联式容器额外的类型别名

2. 哈希桶

3. 无序容器对关键字类型的要求

4. Member functions

4.1 constructor、destructor、operator=

4.1.1 constructor

4.1.2 destructor

4.1.3 operator= 

4.2 Capacity

​4.2.1 empty

4.2.2 size

4.2.3 max_size

4.3 Iterators

4.4 Element lookup

4.4.1 find

4.4.2 count

4.4.3 equal_range

4.5 Modifiers

4.5.1 emplace

4.5.2 emplace_hint

4.5.3 insert

4.5.4 erase

4.5.5 clear

4.5.6 swap

4.6 Buckets

4.6.1 bucket_count

4.6.2 max_bucket_count

4.6.3 bucket_size

4.6.4 bucket

4.7 Hash policy

4.7.1 load_factor

4.7.2 max_load_factor

4.7.3 rehash

4.7.4 reserve

4.8 Observers

4.8.1 hash_function

4.8.2 key_eq

4.8.3 get_allocator

5. Non-member function overloads

5.1 operators

5.2 swap

6. unordered_set对象的遍历方法

6.1 迭代器

6.2 范围for


unordered_set

  1. template < class Key, // unordered_set::key_type/value_type
  2. class Hash = hash<Key>, // unordered_set::hasher
  3. class Pred = equal_to<Key>, // unordered_set::key_equal
  4. class Alloc = allocator<Key> // unordered_set::allocator_type
  5. > class unordered_set;

unordered_set是一种容器,它存储的元素没有特定的顺序,允许根据元素的值快速获取单个元素。

在unordered_set中,一个元素的值与它的键同时存在,从而唯一地标识它。键是不可变的,因此unordered_set中的元素一旦进入容器就不能被修改——但它们可以被插入和删除。

在内部,unordered_set中的元素没有按任何特定的顺序排序,而是根据它们的哈希值组织成,以允许直接通过值快速访问各个元素(平均时间复杂度是常数)。

在通过键访问单个元素时,unordered_set容器比set容器更快,尽管在通过元素子集进行范围迭代时通常效率较低。

容器中的迭代器至少是前向迭代器。

unordered_set定义在头文件unordered_set和命名空间std中。

1. 关联式容器额外的类型别名

key_type此容器类型的关键字类型
mapped_type每个关键字关联的类型;只适用于map
value_type对于set,与key_type相同
对于map,为pair<const key_type, mapped_type>

对于set类型,key_type和value_type是一样的:set中保存的值就是关键字。在一个map中,元素是键值对。即,每个元素是一个pair对象,包含一个关键字和一个关联的值。由于我们不能改变一个元素的关键字,因此这些pair的关键字部分是const的:

  1. set<string>::value_type vl; // v1是一个string
  2. set<string>::key_type v2; // v2是一个string
  3. map<string, int>::value_type v3; // v3是一个pair<const string, int>
  4. map<string, int>::key_type v4; // v4是一个string
  5. map<string, int>::mapped_type v5; // v5是一个int

与序列式容器一样,我们使用作用域运算符来提取一个类型的成员——例如,map<string, int>::key_type。

只有map类型(unordered_map、unordered_multimap、multimap和map)才定义了mapped_type。

2. 哈希桶

无序容器在存储上组织为一组桶,每个桶保存零个或多个元素。无序容器使用一个哈希函数将元素映射到桶。为了访问一个元素,容器首先计算元素的哈希值,它指出应该搜索哪个桶。容器将具有一个特定哈希值的所有元素都保存在相同的桶中。如果容器允许重复关键字,所有具有相同关键字的元素也都会在同一个桶中。因此,无序容器的性能依赖于哈希函数的质量和桶的数量和大小。

对于相同的参数,哈希函数必须总是产生相同的结果。理想情况下,哈希函数还能将每个特定的值映射到唯一的桶。但是,将不同关键字的元素映射到相同的桶也是允许的。当一个桶保存多个元素时,需要顺序搜索这些元素来查找我们想要的那个。计算一个元素的哈希值和在桶中搜索通常都是很快的操作。但是,如果一个桶中保存了很多元素,那么查找一个特定元素就需要大量比较操作。

3. 无序容器对关键字类型的要求

默认情况下,无序容器使用关键字类型的==运算符来比较元素,它们还使用一个hash<key_type>类型的对象来生成每个元素的哈希值。标准库为内置类型(包括指针)提供了hash模板。还为一些标准库类型,包括string和智能指针类型定义了hash。因此,我们可以直接定义关键字是内置类型(包括指针类型)、string还有智能指针类型的无序容器。

但是,我们不能直接定义关键字类型为自定义类类型的无序容器。与容器不同,不能直接使用哈希模板,而必须提供我们自己的hash模板版本。

4. Member functions

4.1 constructor、destructor、operator=

4.1.1 constructor

  1. // empty (1)
  2. explicit unordered_set(size_type n ,
  3. const hasher& hf = hasher(),
  4. const key_equal& eql = key_equal(),
  5. const allocator_type& alloc = allocator_type());
  6. explicit unordered_set(const allocator_type& alloc);
  7. // range (2)
  8. template <class InputIterator>
  9. unordered_set(InputIterator first, InputIterator last,
  10. size_type n,
  11. const hasher& hf = hasher(),
  12. const key_equal& eql = key_equal(),
  13. const allocator_type& alloc = allocator_type());
  14. // copy (3)
  15. unordered_set(const unordered_set& ust);
  16. unordered_set(const unordered_set& ust, const allocator_type& alloc);
  17. // move (4)
  18. unordered_set(unordered_set&& ust);
  19. unordered_set(unordered_set&& ust, const allocator_type& alloc);
  20. // initializer list (5)
  21. unordered_set(initializer_list<value_type> il,
  22. size_type n,
  23. const hasher& hf = hasher(),
  24. const key_equal& eql = key_equal(),
  25. const allocator_type& alloc = allocator_type());
  26. // n表示初始桶的最小数量,不是容器中元素的数量

4.1.2 destructor

~unordered_set();

4.1.3 operator= 

  1. // copy (1)
  2. unordered_set& operator=(const unordered_set& ust);
  3. // move (2)
  4. unordered_set& operator=(unordered_set&& ust);
  5. // initializer list (3)
  6. unordered_set& operator=(intitializer_list<value_type> il);

4.2 Capacity

​4.2.1 empty

  1. bool empty() const noexcept;
  2. // 检测unordered_set是否为空,是返回true,否则返回false

4.2.2 size

  1. size_type size() const noexcept;
  2. // 返回unordered_set中元素的个数

4.2.3 max_size

  1. size_type max_size() const noexcept;
  2. // 返回unordered_set能够容纳的最大元素个数

4.3 Iterators

  1. // begin
  2. // container iterator (1)
  3. iterator begin() noexcept;
  4. const_iterator begin() const noexcept;
  5. // bucket iterator (2)
  6. local_iterator begin(size_type n);
  7. const_local_iterator begin(size_type n) const;
  8. // end
  9. // container iterator (1)
  10. iterator end() noexcept;
  11. const_iterator end() const noexcept;
  12. // bucket iterator (2)
  13. local_iterator end(size_type n);
  14. const_local_iterator end(size_type n) const;
  15. // cbegin
  16. // container iterator (1)
  17. const_iterator cbegin() const noexcept;
  18. // bucket iterator (2)
  19. const_local_iterator cbegin(size_type n) const;
  20. // cend
  21. // container iterator (1)
  22. const_iterator cend() const noexcept;
  23. // bucket iterator (2)
  24. const_local_iterator cend(size_type n) const;
函数功能

begin

&

end

(1)版本begin返回一个迭代器,指向unordered_set中第一个元素

(2)版本begin返回一个迭代器,指向unordered_set中桶n的第一个元素

(1)版本end返回一个迭代器,指向unordered_set中最后一个元素的下一个位置

(2)版本end返回一个迭代器,指向unordered_set中桶n的最后一个元素的下一个位置

cbegin

&

cend

(1)版本cbegin返回一个const迭代器,指向unordered_set中第一个元素

(2)版本cbegin返回一个const迭代器,指向unordered_set中桶n的第一个元素

(1)版本cend返回一个const迭代器,指向unordered_set中最后一个元素的下一个位置

(2)版本cend返回一个const迭代器,指向unordered_set中桶n的最后一个元素的下一个位置

  1. #include <unordered_set>
  2. #include <iostream>
  3. using namespace std;
  4. int main()
  5. {
  6. unordered_set<string> ust{ "iterator","begin","end" };
  7. cout << "ust contains:" << endl;
  8. unordered_set<string>::iterator it = ust.begin();
  9. while (it != ust.end())
  10. {
  11. cout << *it << endl;
  12. ++it;
  13. }
  14. // ust contains :
  15. // iterator
  16. // begin
  17. // end
  18. cout << "ust's buckets contain:" << endl;
  19. for (int i = 0; i < ust.bucket_count(); ++i)
  20. {
  21. cout << "bucket #" << i << " contains:";
  22. unordered_set<string, string>::local_iterator lit = ust.begin(i);
  23. while (lit != ust.end(i))
  24. {
  25. cout << " " << *lit;
  26. ++lit;
  27. }
  28. cout << endl;
  29. }
  30. // ust's buckets contain:
  31. // bucket #0 contains:
  32. // bucket #1 contains:
  33. // bucket #2 contains: end
  34. // bucket #3 contains:
  35. // bucket #4 contains:
  36. // bucket #5 contains:
  37. // bucket #6 contains: begin
  38. // bucket #7 contains: iterator
  39. return 0;
  40. }

4.4 Element lookup

4.4.1 find

  1. iterator find(const key_type& k);
  2. const_iterator find(const key_type& k) const;
  3. // 返回一个迭代器,指向第一个关键字为k的元素,若k不在容器中,则返回end迭代器

4.4.2 count

  1. size_type count(const key_type& k) const;
  2. // 返回关键字等于k的元素的数量
  3. // 对于不允许重复关键字的容器,返回值永远是0或1
  1. #include <unordered_set>
  2. #include <iostream>
  3. using namespace std;
  4. int main()
  5. {
  6. int arr[5] = { 1,2,6,7,8 };
  7. unordered_set<int> ust(arr, arr + 5);
  8. auto it = ust.find(2);
  9. if (it != ust.end())
  10. {
  11. cout << "2在unordered_set中" << endl;
  12. }
  13. else
  14. {
  15. cout << "2不在unordered_set中" << endl;
  16. }
  17. // 2在unordered_set中
  18. it = ust.find(3);
  19. if (it != ust.end())
  20. {
  21. cout << "3在unordered_set中" << endl;
  22. }
  23. else
  24. {
  25. cout << "3不在unordered_set中" << endl;
  26. }
  27. // 3不在unordered_set中
  28. if (ust.count(7))
  29. {
  30. cout << "7在unordered_set中" << endl;
  31. }
  32. else
  33. {
  34. cout << "7不在unordered_set中" << endl;
  35. }
  36. // 7在unordered_set中
  37. if (ust.count(5))
  38. {
  39. cout << "5在unordered_set中" << endl;
  40. }
  41. else
  42. {
  43. cout << "5不在unordered_set中" << endl;
  44. }
  45. // 5不在unordered_set中
  46. return 0;
  47. }

4.4.3 equal_range

  1. pair<iterator, iterator> equal_range(const key_type& k);
  2. pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
  3. // 返回一个迭代器pair,表示关键字等于k的元素的范围(左闭右开的区间)
  4. // 若k不存在,pair的两个成员均为end迭代器
  5. // 对于不允许重复关键字的容器,返回的范围最多只包含一个元素

4.5 Modifiers

4.5.1 emplace

  1. template <class... Args> pair<iterator, bool> emplace(Args&&... args);
  2. // 对应insert,区别是:
  3. // 当调用insert时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中
  4. // 当调用emplace时,则是将参数传递给元素类型的构造函数,然后使用这些参数在容器管理的内存空间中直接构造元素

4.5.2 emplace_hint

  1. template <class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
  2. // 对应insert的(3)和(4),区别是:
  3. // 当调用insert时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中
  4. // 当调用emplace时,则是将参数传递给元素类型的构造函数,然后使用这些参数在容器管理的内存空间中直接构造元素

4.5.3 insert

  1. // (1) 成功返回pair<插入位置, true>,失败返回pair<插入位置, false>
  2. pair<iterator, bool> insert(const value_type& val);
  3. // (2)
  4. pair<iterator, bool> insert(value_type&& val);
  5. // (3)
  6. iterator insert(const_iterator hint, const value_type& val);
  7. // (4)
  8. iterator insert(const_iterator hint, value_type&& val);
  9. // (5)
  10. template <class InputIterator> void insert(InputIterator first, InputIterator last);
  11. // (6)
  12. void insert(initializer_list<value_type> il);
  13. // 插入

4.5.4 erase

  1. // by position(1)
  2. iterator erase(const_iterator position);
  3. // by key(2)
  4. size_type erase(const key_type& k);
  5. // range(3)
  6. iterator erase(const_iterator first, const_iterator last);
  7. // 删除

4.5.5 clear

  1. void clear() noexcept;
  2. // 清空

4.5.6 swap

  1. void swap(unordered_set& ust);
  2. // 交换

4.6 Buckets

4.6.1 bucket_count

  1. size_type bucket_count() const noexcept;
  2. // 返回unordered_set中桶的个数

4.6.2 max_bucket_count

  1. size_type max_bucket_count() const noexcept;
  2. // 返回unordered_set能够容纳的最大桶个数

4.6.3 bucket_size

  1. size_type bucket_size(size_type n) const;
  2. // 返回桶n中元素的个数

4.6.4 bucket

  1. size_type bucket(const key_type& k) const;
  2. // 返回关键字为k的元素所在的桶号

4.7 Hash policy

4.7.1 load_factor

  1. float load_factor() const noexcept;
  2. // 返回负载因子(每个桶平均元素的数量,元素的数量/桶的数量)

4.7.2 max_load_factor

  1. // get(1)
  2. float max_load_factor() const noexcept;
  3. // set(2)
  4. void max_load_factor(float z);
  5. // 获取或设置最大负载因子

4.7.3 rehash

  1. void rehash(size_type n);
  2. // 设置桶的数量

4.7.4 reserve

  1. void reserve(size_type n);
  2. // 将桶数设置为最适合包含至少n个元素的桶数

4.8 Observers

4.8.1 hash_function

  1. hasher hash_function() const;
  2. // 返回哈希函数

4.8.2 key_eq

  1. key_equal key_eq() const;
  2. // 返回关键字等价比较谓词

4.8.3 get_allocator

  1. allocator_type get_allocator() const noexcept;
  2. // 返回空间配置器

5. Non-member function overloads

5.1 operators

  1. // equality (1)
  2. template <class Key, class Hash, class Pred, class Alloc>
  3. bool operator==(const unordered_set<Key, Hash, Pred, Alloc>& lhs, const unordered_set<Key, Hash, Pred, Alloc>& rhs);
  4. // inequality (2)
  5. template <class Key, class Hash, class Pred, class Alloc>
  6. bool operator!=(const unordered_set<Key, Hash, Pred, Alloc>& lhs, const unordered_set<Key, Hash, Pred, Alloc>& rhs);

5.2 swap

  1. template <class Key, class Hash, class Pred, class Alloc>
  2. void swap(unordered_set<Key, Hash, Pred, Alloc>& lhs, unordered_set<Key, Hash, Pred, Alloc>& rhs);

6. unordered_set对象的遍历方法

6.1 迭代器

  1. #include <unordered_set>
  2. #include <iostream>
  3. using namespace std;
  4. int main()
  5. {
  6. int arr[5] = { 1,2,6,7,8 };
  7. unordered_set<int> ust(arr, arr + 5);
  8. unordered_set<int>::iterator it = ust.begin();
  9. while (it != ust.end())
  10. {
  11. cout << *it << " ";
  12. ++it;
  13. }
  14. cout << endl;
  15. // 1 2 6 7 8
  16. return 0;
  17. }

6.2 范围for

  1. #include <unordered_set>
  2. #include <iostream>
  3. using namespace std;
  4. int main()
  5. {
  6. int arr[5] = { 1,2,6,7,8 };
  7. unordered_set<int> ust(arr, arr + 5);
  8. for (auto& e : ust)
  9. {
  10. cout << e << " ";
  11. }
  12. cout << endl;
  13. // 1 2 6 7 8
  14. return 0;
  15. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/103427?site
推荐阅读
相关标签
  

闽ICP备14008679号