【C++】unordered系列容器

【C++】unordered系列容器

1、unordered容器介绍

unordered容器是C++标准库中提供的一组无序关联式容器,用于存储和管理无序的数据集合。这些容器的特点是快速的查找、插入和删除操作,其内部实现通常基于哈希表(hash table)。

C++标准库提供了四种unordered容器:

  1. unordered_set:无序唯一元素集合,存储一组唯一的元素,不允许重复。
  2. unordered_multiset:无序元素集合,存储一组元素,允许重复。
  3. unordered_map:无序键值对集合,存储一组唯一的键值对,每个键只能出现一次。
  4. unordered_multimap:无序键值对集合,存储一组键值对,允许键的重复。

这些容器的特点如下:

  1. 无序性:unordered容器中的元素没有特定的顺序,与插入的顺序无关。元素的存储位置是根据其哈希值来确定的,而不是根据比较操作符。这使得无序容器在查找操作上具有常数时间复杂度,而有序容器通常需要对元素进行排序和比较。

  2. 哈希表实现:unordered容器内部通常使用哈希表实现。哈希表是一种将元素的键映射到存储位置的数据结构,通过使用哈希函数将键转换为存储桶的索引。这样可以在平均情况下实现常数时间的插入、查找和删除操作。

  3. 高效的插入和删除:由于无序容器使用哈希表,插入和删除操作的时间复杂度通常是常数时间。这使得无序容器特别适用于需要频繁插入和删除元素的场景。

  4. 自定义键类型:无序容器支持使用自定义类型作为键。为了支持自定义类型,需要提供自定义的哈希函数和相等比较函数。

使用unordered容器的步骤如下:

  1. 包含头文件:在使用unordered容器之前,需要包含 <unordered_set>, <unordered_map> 头文件,并使用适当的命名空间(例如 std)。

  2. 创建容器对象:使用容器的类型名称和模板参数,声明一个容器对象。

  3. 插入和访问元素:使用容器的成员函数来插入和访问元素。

  4. 查找和删除元素:使用成员函数进行元素的查找和删除操作。

无序容器还提供了许多其他的成员函数和操作,如 size() 返回容器中的元素数量,clear() 清空容器等。具体的使用方法和注意事项可以在C++标准库的文档中找到。

2、unordered_map

2.1 介绍

  1. unordered_map是一种关联式容器,用于存储键值对(key-value pair)。通过键(key),可以快速地索引到与之关联的值(value)。

  2. 在unordered_map中,键用于唯一地标识元素,而映射值则是与键相关联的对象。键和映射值的类型可以不同。

  3. unordered_map内部使用哈希表(hash table)实现,相同哈希值的键值对被放置在相同的桶中。它并不对键值对按任何特定顺序进行排序,而是根据哈希值来组织元素。

  4. 由于unordered_map的内部实现是基于哈希表,通过键进行单个元素的访问速度比有序容器(如map)要快。然而,当需要遍历元素子集时,unordered_map的效率可能较低,因为元素的顺序是无序的。

  5. unordered_map实现了直接访问操作符(operator[]),允许使用键作为参数直接访问对应的值。例如:value = myMap[key];

  6. unordered_map的迭代器至少是前向迭代器,可以用于遍历容器中的元素。可以使用迭代器来访问键值对、进行插入、删除等操作。

2.2 接口说明以及使用

2.2.1 构造

unordered_map提供了多种构造函数,可以根据不同的需求进行初始化。以下是一些常用的构造函数及其使用示例:

  1. 默认构造函数:

    std::unordered_map<Key, T> myMap;
    

    示例:

    std::unordered_map<std::string, int> myMap; // 创建一个空的unordered_map
    
  2. 初始化列表构造函数:

    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
    
  3. 范围构造函数:

    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
    
  4. 拷贝构造函数:

    std::unordered_map<Key, T> myMap(otherMap);
    

    示例:

    std::unordered_map<std::string, int> myMap(otherMap); // 通过拷贝构造函数创建unordered_map
    
  5. 移动构造函数:

    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中,您可以使用以下两个成员函数来查询容器的状态和大小:

  1. 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;
    }
    
  2. 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中,可以使用以下四个成员函数来获取迭代器以遍历容器中的元素:

  1. begin():返回指向unordered_map中第一个元素的迭代器。

    iterator begin();
    

    示例:

    std::unordered_map<std::string, int> myMap = {
          
          {
          
          "apple", 5}, {
          
          "banana", 3}, {
          
          "orange", 2}};
    auto it = myMap.begin(); // 获取指向第一个元素的迭代器
    
  2. end():返回指向unordered_map中最后一个元素之后位置的迭代器。

    iterator end();
    

    示例:

    std::unordered_map<std::string, int> myMap = {
          
          {
          
          "apple", 5}, {
          
          "banana", 3}, {
          
          "orange", 2}};
    auto it = myMap.end(); // 获取指向最后一个元素之后位置的迭代器
    
  3. 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迭代器
    
  4. 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中,可以使用以下几个成员函数来插入、删除、清空和交换容器中的元素:

  1. 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());
    
  2. 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());
    }
    
  3. clear():清空unordered_map中的所有键值对,使其成为空容器。

    void clear();
    

    示例:

    std::unordered_map<std::string, int> myMap = {
          
          {
          
          "apple", 5}, {
          
          "banana", 3}, {
          
          "orange", 2}};
    myMap.clear(); // 清空unordered_map
    
  4. 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中,可以使用以下两个成员函数来查找键和计算特定键的数量:

  1. 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;
    }
    
  2. 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的内部结构和性能。

以下是一些常见的桶操作:

  1. bucket_count():返回unordered_map中的存储桶的数量。

    size_type bucket_count() const;
    
  2. bucket_size():返回特定存储桶中的元素数量。

    size_type bucket_size(size_type n) const;
    
  3. bucket():返回给定键的元素所在的存储桶的索引。

    size_type bucket(const key_type& key) const;
    
  4. begin(bucket_index):返回指向特定存储桶中第一个元素的迭代器。

    local_iterator begin(size_type n);
    
  5. end(bucket_index):返回指向特定存储桶中最后一个元素之后位置的迭代器。

    local_iterator end(size_type n);
    

通过这些桶操作可以了解unordered_map中存储桶的数量、每个存储桶中的元素数量,以及特定键所在的存储桶索引。还可以使用迭代器来遍历特定存储桶中的元素。

这些桶操作是unordered_map的特定成员函数,用于提供对存储桶的访问和操作功能。

3、unordered_set

具体接口函数可以自行查找

这里说明它与unordered_map间的异同点:

unordered_map和unordered_set是C++标准库中提供的两种容器,它们有以下相同点和不同点:

相同点:

  1. 底层实现:unordered_map和unordered_set都是基于哈希表(hash table)实现的,利用哈希函数将元素映射到存储桶中,以实现高效的插入、查找和删除操作。

  2. 查找效率:无论是unordered_map还是unordered_set,都具有快速的查找效率。由于哈希表的特性,平均情况下,它们的查找操作的时间复杂度为常数。

  3. 迭代器:unordered_map和unordered_set都提供了迭代器(iterator),可以用于遍历容器中的元素。

  4. 自定义键类型:两者都支持使用自定义类型作为键。需要提供自定义的哈希函数和相等比较函数来支持自定义键类型。

不同点:

  1. 存储方式:unordered_map存储键值对(key-value pair),而unordered_set只存储唯一的值(value)。unordered_map使用键来唯一标识和访问每个元素,而unordered_set仅依靠值来唯一标识每个元素。

  2. 元素类型:unordered_map中的元素是键值对,其中键和值的类型可以不同。而unordered_set中的元素只包含值,类型由模板参数指定。

  3. 存储结构:由于unordered_map存储键值对,因此它的存储结构相对于unordered_set要复杂一些。unordered_map中的每个存储桶都存储了一个键值对,而unordered_set中的每个存储桶只存储一个值。

  4. 插入操作:在unordered_map中,插入一个新的键值对时,需要同时提供键和值。而在unordered_set中,插入一个新值只需要提供该值即可。

总体上,unordered_map适用于需要存储键值对的情况,可以通过键快速访问对应的值;而unordered_set适用于只需存储独特值的情况,可以快速判断某个值是否存在。

猜你喜欢

转载自blog.csdn.net/qq_64893500/article/details/131636810
今日推荐