C++进阶之一篇文章教会你什么是map和set(下)

简介: 6.set观察器和操作成员函数Observerskey_comp(返回键的比较对象):key_compare key_comp() const;

6.set观察器和操作成员函数

Observers

  1. key_comp(返回键的比较对象):
  • key_compare key_comp() const;
  • 返回一个键的比较对象,用于比较容器中键的大小关系。
  1. value_comp(返回值的比较对象):
  • value_compare value_comp() const;
  • 返回一个值的比较对象,用于比较容器中的值的大小关系。

Operations

  1. find(查找元素):
  • iterator find(const key_type& key);
  • 返回一个迭代器,指向键等于给定键的元素。如果未找到元素,则返回指向容器末尾的迭代器 end()
  1. count(计算特定值的元素个数):
  • size_type count(const key_type& key);
  • 返回具有指定值的元素个数。通常情况下,由于键是唯一的,结果将是0或1。
  1. lower_bound(返回下限迭代器):
  • iterator lower_bound(const key_type& key);
  • 返回一个迭代器,指向第一个大于或等于给定键的元素位置。
  1. upper_bound(返回上限迭代器):
  • iterator upper_bound(const key_type& key);
  • 返回一个迭代器,指向第一个大于给定键的元素位置。
  1. equal_range(获取相等元素的范围):
  • pair<iterator, iterator> equal_range(const key_type& key);
  • 返回一个包含两个迭代器的pair,第一个迭代器指向第一个等于给定键的元素,第二个迭代器指向第一个大于给定键的元素。

示例

#include <iostream>
#include <set>
int main() {
    std::set<int> mySet = {1, 2, 3, 4, 5};
    // 使用 key_comp 获取键的比较对象
    std::set<int>::key_compare keyComp = mySet.key_comp();
    // 使用 value_comp 获取值的比较对象
    std::set<int>::value_compare valueComp = mySet.value_comp();
    // 查找元素
    std::set<int>::iterator it = mySet.find(3);
    if (it != mySet.end()) {
        std::cout << "找到元素 3" << std::endl;
    } else {
        std::cout << "未找到元素 3" << std::endl;
    }
    // 计算特定值的元素个数
    size_t count = mySet.count(4);
    std::cout << "值为 4 的元素个数: " << count << std::endl;
    // 获取下限迭代器
    std::set<int>::iterator lower = mySet.lower_bound(2);
    std::cout << "下限迭代器指向大于或等于 2 的元素位置: " << *lower << std::endl;
    // 获取上限迭代器
    std::set<int>::iterator upper = mySet.upper_bound(4);
    std::cout << "上限迭代器指向大于 4 的元素位置: " << *upper << std::endl;
    // 获取相等元素的范围
    std::pair<std::set<int>::iterator, std::set<int>::iterator> range = mySet.equal_range(3);
    std::cout << "相等元素范围: [" << *(range.first) << ", " << *(range.second) << "]" << std::endl;
    return 0;
}

7.set应用场景

#include <set>
void TestSet()
{
    // 用数组array中的元素构造set
    int array[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 1, 3, 5, 7, 9, 2, 4,6, 8, 0 };
    set<int> s(array, array+sizeof(array)/sizeof(array));
    cout << s.size() << endl;
    // 正向打印set中的元素,从打印结果中可以看出:set可去重
    for (auto& e : s)
    cout << e << " ";
    cout << endl;
    // 使用迭代器逆向打印set中的元素
    for (auto it = s.rbegin(); it != s.rend(); ++it)
    cout << *it << " ";
    cout << endl;
    // set中值为3的元素出现了几次
    cout << s.count(3) << endl;
}

set和multiset的区别

std::setstd::multiset 都是 C++ 标准库中的关联式容器,它们用于存储一组元素,且元素是按照一定的顺序排列的。然而,它们之间有一个关键的区别:

  1. 唯一性:
  • std::setstd::set 中的元素是唯一的,不允许重复的元素存在。如果试图插入重复的元素,新元素将不会被插入。
  • std::multisetstd::multiset 允许存储重复的元素,可以插入多个具有相同键值的元素。

下面是更详细的比较:

  • std::set
  • 元素是唯一的,不允许重复。
  • 插入操作会检查元素是否已存在,如果已存在则插入不成功。
  • 查找操作在 O(log n) 的时间内完成,因为元素唯一。
  • 适用于需要维护一组唯一值的情况,例如去重操作。
  • std::multiset
  • 允许存储重复的元素,不会检查重复性。
  • 插入操作总是成功,允许存储多个相同键值的元素。
  • 查找操作在 O(log n) 的时间内完成,因为仍然具有排序特性。
  • 适用于需要允许重复值的情况,例如统计元素出现次数。
  • multiset在底层实际存储的是<int, int>的键值对。

在选择使用 std::set 还是 std::multiset 时,取决于你的数据需求。如果需要维护一组唯一的值,使用 std::set;如果允许重复值,并且需要统计重复值的出现次数,使用 std::multiset

map

1.map模板参数列表

template < class Key,                                     // map::key_type
           class T,                                       // map::mapped_type
           class Compare = less<Key>,                     // map::key_compare
           class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
           > class map;

std::map是一个关联式容器,它提供了key-value对的存储和管理。以下是代码中各个模板参数的解释:

  • Key:表示std::map容器中的键类型,也就是键值对中的键的类型。
  • T:表示std::map容器中的值类型,也就是键值对中的值的类型。
  • Compare:表示比较键的方式的函数对象,默认使用 std::less<Key>,可以根据需要自定义键的比较方式。
  • Alloc:表示用于分配内存的分配器类型,默认使用 std::allocator<std::pair<const Key, T>>,通常情况下不需要自定义。

通过这个模板声明,你可以创建不同类型的std::map容器,以存储不同类型的key-value对。例如,如果要创建一个存储整数键和字符串值的std::map容器,可以这样使用:

std::map<int, std::string> myMap;

这将创建一个std::map容器,其中键的类型是整数 (int),值的类型是字符串 (std::string)。您可以使用该容器来存储和检索整数和字符串之间的映射关系。

成员类型

2.map的构造

  1. empty(默认构造函数):
  • explicit map(const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());
  • 这是std::map的默认构造函数,它创建一个空的std::map对象。
  • comp 参数是可选的,表示用于比较键的自定义比较函数,默认使用 key_compare(),即使用std::less<Key>
  • alloc 参数是可选的,表示用于内存分配的自定义分配器,默认使用 allocator_type(),即使用std::allocator<std::pair<const Key, T>>
  1. range(范围构造函数):
  • template <class InputIterator> map(InputIterator first, InputIterator last, const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());
  • 这个构造函数允许您从一个范围(由迭代器 firstlast 定义)初始化std::map容器。
  • comp 参数是可选的,表示用于比较键的自定义比较函数,默认使用 key_compare()
  • alloc 参数是可选的,表示用于内存分配的自定义分配器,默认使用 allocator_type()
  1. copy(复制构造函数):
  • map(const map& x);
  • 这个构造函数用于创建一个新的std::map容器,并以另一个std::map容器 x 的内容进行初始化,即复制x中的键值对到新的容器中。

示例

#include <iostream>
#include <map>
int main() {
    // 使用默认构造函数创建一个空的 std::map
    std::map<int, std::string> myMap1;
    // 使用范围构造函数创建并初始化 std::map
    std::map<int, std::string> myMap2 = {{1, "One"}, {2, "Two"}, {3, "Three"}};
    // 使用复制构造函数创建一个与 myMap2 相同内容的副本
    std::map<int, std::string> myMap3(myMap2);
    // 输出容器内容
    std::cout << "myMap1: " << myMap1.size() << " elements" << std::endl;
    std::cout << "myMap2: " << myMap2.size() << " elements" << std::endl;
    std::cout << "myMap3: " << myMap3.size() << " elements" << std::endl;
    return 0;
}

在此示例中,我们演示了三种不同的std::map构造函数的使用方式,包括默认构造函数、范围构造函数和复制构造函数。根据构造函数的不同用途,可以创建空容器、初始化容器或复制另一个容器的内容。

赋值运算符重载

将一个 std::map 的内容复制到另一个已存在的 std::map 中。例如:

std::map<int, std::string> sourceMap = {{1, "One"}, {2, "Two"}};
std::map<int, std::string> targetMap;
targetMap = sourceMap; // 使用拷贝赋值运算符将内容复制到目标容器

它会创建一个新的 std::map 容器,其中包含与原始容器相同的键值对。这是一种将数据从一个容器复制到另一个容器的常见方式。

3.map迭代器

std::map容器提供了多种迭代器,用于访问容器中的元素。以下是这些迭代器的详细描述:

  1. begin
  • iterator begin();
  • 返回一个迭代器,指向std::map容器中第一个元素的位置。
  1. end
  • iterator end();
  • 返回一个迭代器,指向std::map容器中的末尾(尾后位置)。
  1. rbegin
  • reverse_iterator rbegin();
  • 返回一个逆向迭代器,指向std::map容器中的最后一个元素的位置。
  1. rend
  • reverse_iterator rend();
  • 返回一个逆向迭代器,指向std::map容器中的逆向末尾(逆向尾后位置)。
  1. cbegin
  • const_iterator cbegin() const;
  • 返回一个常量迭代器,指向std::map容器中第一个元素的位置。用于只读访问。
  1. cend
  • const_iterator cend() const;
  • 返回一个常量迭代器,指向std::map容器中的末尾(尾后位置)。用于只读访问。
  1. crbegin
  • const_reverse_iterator crbegin() const;
  • 返回一个常量逆向迭代器,指向std::map容器中的最后一个元素的位置。用于只读访问。
  1. crend
  • const_reverse_iterator crend() const;
  • 返回一个常量逆向迭代器,指向std::map容器中的逆向末尾(逆向尾后位置)。用于只读访问。

示例

#include <iostream>
#include <map>
int main() {
    // 创建一个 std::map 容器并初始化
    std::map<int, std::string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}};
    // 使用正向迭代器遍历容器
    std::cout << "正向迭代器遍历容器:" << std::endl;
    for (std::map<int, std::string>::iterator it = myMap.begin(); it != myMap.end(); ++it) {
        std::cout << "键: " << it->first << ", 值: " << it->second << std::endl;
    }
    // 使用逆向迭代器遍历容器
    std::cout << "逆向迭代器遍历容器:" << std::endl;
    for (std::map<int, std::string>::reverse_iterator rit = myMap.rbegin(); rit != myMap.rend(); ++rit) {
        std::cout << "键: " << rit->first << ", 值: " << rit->second << std::endl;
    }
    // 使用常量迭代器遍历容器(只读访问)
    std::cout << "常量迭代器遍历容器:" << std::endl;
    for (std::map<int, std::string>::const_iterator cit = myMap.cbegin(); cit != myMap.cend(); ++cit) {
        std::cout << "键: " << cit->first << ", 值: " << cit->second << std::endl;
    }
    // 使用常量逆向迭代器遍历容器(只读访问)
    std::cout << "常量逆向迭代器遍历容器:" << std::endl;
    for (std::map<int, std::string>::const_reverse_iterator crit = myMap.crbegin(); crit != myMap.crend(); ++crit) {
        std::cout << "键: " << crit->first << ", 值: " << crit->second << std::endl;
    }
    return 0;
}

这个示例演示了如何使用不同类型的迭代器遍历std::map容器中的元素:

  • 使用正向迭代器 begin()end() 遍历容器。
  • 使用逆向迭代器 rbegin()rend() 逆向遍历容器。
  • 使用常量迭代器 cbegin()cend() 以只读方式遍历容器。
  • 使用常量逆向迭代器 crbegin()crend() 以只读方式逆向遍历容器。

4.map容量和元素访问函数

这些是关于std::map容器的一些容量和元素访问相关的成员函数:

  1. empty(检查是否为空):
  • bool empty() const;
  • 用于检查std::map容器是否为空。如果容器为空,返回true;否则返回false
  1. size(返回容器大小):
  • size_type size() const;
  • 返回std::map容器中键值对的数量,也就是容器的大小。
  1. max_size(返回最大容量):
  • size_type max_size() const;
  • 返回std::map容器可以容纳的最大元素数量。这通常受到系统内存限制的影响。
  1. operator[](访问元素):
  • T& operator[](const key_type& key);
  • 允许通过键访问容器中的元素。如果键存在,则返回相应的值的引用,如果不存在,则会插入一个具有该键的默认值,并返回引用。请注意,如果键不存在,将插入一个具有默认值的键值对。
  1. at(访问元素):
  • T& at(const key_type& key);
  • 允许通过键访问容器中的元素,类似于 operator[]。但与 operator[] 不同,如果键不存在,at 会抛出 std::out_of_range 异常。

示例

#include <iostream>
#include <map>
int main() {
    std::map<int, std::string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}};
    // 检查容器是否为空
    if (myMap.empty()) {
        std::cout << "容器为空" << std::endl;
    } else {
        std::cout << "容器不为空" << std::endl;
    }
    // 获取容器的大小
    std::cout << "容器大小为: " << myMap.size() << std::endl;
    // 访问容器中的元素
    std::string value = myMap[2]; // 使用 operator[]
    std::cout << "键 2 对应的值为: " << value << std::endl;
    try {
        std::string value = myMap.at(4); // 键 4 不存在,会抛出异常
    } catch (const std::out_of_range& e) {
        std::cerr << "键 4 不存在: " << e.what() << std::endl;
    }
    return 0;
}

在此示例中,我们演示了如何使用std::map容器的容量和元素访问成员函数,包括检查容器是否为空、获取容器大小、通过键访问元素以及处理键不存在的情况。

5.map修改器函数

  1. insert(插入元素):
  • pair<iterator, bool> insert(const value_type& value);
  • 用于插入键值对(键值对的类型为 value_type)到std::map容器中。如果插入成功,返回一个迭代器指向插入的元素和 true;如果元素已存在,则返回一个迭代器指向现有元素和 false
  1. erase(删除元素):
  • iterator erase(iterator position);
  • size_type erase(const key_type& key);
  • 用于删除容器中的元素。第一种形式删除由迭代器 position 指定的元素,并返回指向下一个元素的迭代器。第二种形式删除指定键的元素,并返回删除的元素数量。
  1. swap(交换内容):
  • void swap(map& x);
  • 用于交换两个std::map容器的内容,即交换键值对。交换后,两个容器的内容完全交换。
  1. clear(清空内容):
  • void clear();
  • 用于清空std::map容器中的所有元素,使容器成为空容器。
  1. emplace(构造并插入元素):
  • pair<iterator, bool> emplace(Args&&... args);
  • 允许构造并插入元素,其中 Args 是键值对的构造参数。如果插入成功,返回一个迭代器指向插入的元素和 true;如果元素已存在,则返回一个迭代器指向现有元素和 false
  1. emplace_hint(构造并插入元素带提示):
  • iterator emplace_hint(const_iterator position, Args&&... args);
  • 允许构造并插入元素,其中 Args 是键值对的构造参数,并且可以提供插入位置的提示。返回一个迭代器指向插入的元素。

示例

#include <iostream>
#include <map>
int main() {
    std::map<int, std::string> myMap;
    // 插入元素
    myMap.insert(std::make_pair(1, "One"));
    myMap.insert(std::make_pair(2, "Two"));
    // 删除元素
    myMap.erase(2);
    // 交换容器内容
    std::map<int, std::string> anotherMap = {{3, "Three"}, {4, "Four"}};
    myMap.swap(anotherMap);
    // 清空容器
    myMap.clear();
    // 构造并插入元素
    myMap.emplace(5, "Five");
    // 使用 emplace_hint 插入元素
    std::map<int, std::string>::iterator it = myMap.emplace_hint(myMap.begin(), 6, "Six");
    // 输出容器内容
    for (const auto& pair : myMap) {
        std::cout << "键: " << pair.first << ", 值: " << pair.second << std::endl;
    }
    return 0;
}

在此示例中,我们演示了如何使用std::map容器的修改器成员函数,包括插入、删除、交换和清空元素,以及使用 emplaceemplace_hint 插入元素的方式。

6.map观察器和操作成员函数

Observers

  1. key_comp(返回键的比较对象):
  • key_compare key_comp() const;
  • 返回一个键的比较对象,用于比较容器中键的大小关系。
  1. value_comp(返回值的比较对象):
  • value_compare value_comp() const;
  • 返回一个值的比较对象,用于比较容器中的值的大小关系。

Operations

  1. find(查找元素):
  • iterator find(const key_type& key);
  • 返回一个迭代器,指向键等于给定键的元素。如果未找到元素,则返回指向容器末尾的迭代器 end()
  1. count(计算特定键的元素个数):
  • size_type count(const key_type& key);
  • 返回具有指定键的元素个数。通常情况下,由于键是唯一的,结果将是0或1。
  1. lower_bound(返回下限迭代器):
  • iterator lower_bound(const key_type& key);
  • 返回一个迭代器,指向第一个大于或等于给定键的元素位置。
  1. upper_bound(返回上限迭代器):
  • iterator upper_bound(const key_type& key);
  • 返回一个迭代器,指向第一个大于给定键的元素位置。
  1. equal_range(获取相等元素的范围):
  • pair<iterator, iterator> equal_range(const key_type& key);
  • 返回一个包含两个迭代器的pair,第一个迭代器指向第一个等于给定键的元素,第二个迭代器指向第一个大于给定键的元素。

以下是示例用法

#include <iostream>
#include <map>
int main() {
    std::map<int, std::string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}};
    // 使用 find 查找元素
    std::map<int, std::string>::iterator it = myMap.find(2);
    if (it != myMap.end()) {
        std::cout << "找到键 2,值为: " << it->second << std::endl;
    } else {
        std::cout << "未找到键 2" << std::endl;
    }
    // 使用 count 计算特定键的元素个数
    size_t count = myMap.count(3);
    std::cout << "键 3 的元素个数: " << count << std::endl;
    // 使用 lower_bound 获取下限迭代器
    std::map<int, std::string>::iterator lower = myMap.lower_bound(2);
    std::cout << "下限迭代器指向键 2,值为: " << lower->second << std::endl;
    // 使用 upper_bound 获取上限迭代器
    std::map<int, std::string>::iterator upper = myMap.upper_bound(2);
    std::cout << "上限迭代器指向大于键 2 的元素,值为: " << upper->second << std::endl;
    // 使用 equal_range 获取相等元素的范围
    std::pair<std::map<int, std::string>::iterator, std::map<int, std::string>::iterator> range = myMap.equal_range(2);
    std::cout << "相等元素范围: [" << range.first->second << ", " << range.second->second << "]" << std::endl;
    return 0;
}

在此示例中,我们演示了如何使用std::map容器的观察器和操作成员函数,包括查找元素、计算特定键的元素个数、获取下限迭代器、获取上限迭代器以及获取相等元素的范围。这些函数使得在std::map容器中执行查找和搜索操作变得非常方便。

7.map应用场景

#include <string>
#include <map>
void TestMap()
{
  map<string, string> m;
  // 向map中插入元素的方式:
  // 将键值对<"peach","桃子">插入map中,用pair直接来构造键值对
  m.insert(pair<string, string>("peach", "桃子"));
  // 将键值对<"peach","桃子">插入map中,用make_pair函数来构造键值对
  m.insert(make_pair("banan", "香蕉"));
  // 借用operator[]向map中插入元素
  /*
  operator[]的原理是:
  用<key, T()>构造一个键值对,然后调用insert()函数将该键值对插入到map中
  如果key已经存在,插入失败,insert函数返回该key所在位置的迭代器
  如果key不存在,插入成功,insert函数返回新插入元素所在位置的迭代器
  operator[]函数最后将insert返回值键值对中的value返回
  */
  // 将<"apple", "">插入map中,插入成功,返回value的引用,将“苹果”赋值给该引用结果,
    m["apple"] = "苹果";
  // key不存在时抛异常
  //m.at("waterme") = "水蜜桃";
    cout << m.size() << endl;
    // 用迭代器去遍历map中的元素,可以得到一个按照key排序的序列
    for (auto& e : m)
      cout << e.first << "--->" << e.second << endl;
    cout << endl;
    // map中的键值对key一定是唯一的,如果key存在将插入失败
    auto ret = m.insert(make_pair("peach", "桃色"));
    if (ret.second)
      cout << "<peach, 桃色>不在map中, 已经插入" << endl;
    else
      cout << "键值为peach的元素已经存在:" << ret.first->first << "--->"
      << ret.first->second << " 插入失败" << endl;
    // 删除key为"apple"的元素
    m.erase("apple");
    if (1 == m.count("apple"))
      cout << "apple还在" << endl;
    else
      cout << "apple被吃了" << endl;
}

map和multimap的区别

std::mapstd::multimap 都是 C++ 标准库中的关联式容器,它们用于存储一组key-value对(键值对),并根据键对元素进行排序。它们之间的主要区别在于唯一性和允许重复性:

std::map

  • std::map 是一个关联容器,其中的键是唯一的,每个键只能关联一个值。
  • 如果试图插入已存在的键,新值将覆盖旧值。
  • 使用 operator[]insert 插入元素。
  • 查找操作(例如 findcountlower_boundupper_bound)返回匹配的唯一元素。

std::multimap

  • std::multimap 也是一个关联容器,允许多个具有相同键的值存在。
  • 可以插入多个具有相同键的值,不会覆盖旧值。
  • 使用 insert 插入元素。
  • 查找操作返回匹配的所有元素,因为可以有多个相同键的元素。

以下是示例用法和比较:

std::map 示例:

#include <iostream>
#include <map>
int main() {
    std::map<int, std::string> myMap;
    // 插入键值对
    myMap[1] = "One";
    myMap[2] = "Two";
    myMap[3] = "Three";
    // 重复键值对将覆盖旧值
    myMap[2] = "New Two";
    // 查找键为 2 的元素
    std::map<int, std::string>::iterator it = myMap.find(2);
    if (it != myMap.end()) {
        std::cout << "找到键 2,值为: " << it->second << std::endl;
    }
    return 0;
}

std::multimap 示例:

#include <iostream>
#include <map>
int main() {
    std::multimap<int, std::string> myMultiMap;
    // 插入多个具有相同键的值
    myMultiMap.insert(std::make_pair(1, "One"));
    myMultiMap.insert(std::make_pair(2, "Two"));
    myMultiMap.insert(std::make_pair(2, "Another Two"));
    myMultiMap.insert(std::make_pair(3, "Three"));
    // 查找键为 2 的所有元素
    auto range = myMultiMap.equal_range(2);
    for (auto it = range.first; it != range.second; ++it) {
        std::cout << "找到键 2,值为: " << it->second << std::endl;
    }
    return 0;
}

总结

  • 如果需要维护唯一key-value对,使用 std::map
  • 如果允许具有相同键的多个值存在,使用 std::multimap


相关文章
|
2月前
|
存储 缓存 JavaScript
Set和Map有什么区别?
Set和Map有什么区别?
235 1
|
6月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
166 2
|
6月前
|
存储 算法 C++
【c++丨STL】map/multimap的使用
本文详细介绍了STL关联式容器中的`map`和`multimap`的使用方法。`map`基于红黑树实现,内部元素按键自动升序排列,存储键值对,支持通过键访问或修改值;而`multimap`允许存在重复键。文章从构造函数、迭代器、容量接口、元素访问接口、增删操作到其他操作接口全面解析了`map`的功能,并通过实例演示了如何用`map`统计字符串数组中各元素的出现次数。最后对比了`map`与`set`的区别,强调了`map`在处理键值关系时的优势。
317 73
|
3月前
|
存储 JavaScript 前端开发
for...of循环在遍历Set和Map时的注意事项有哪些?
for...of循环在遍历Set和Map时的注意事项有哪些?
97 0
|
3月前
|
存储 C++ 容器
unordered_set、unordered_multiset、unordered_map、unordered_multimap的介绍及使用
unordered_set是不按特定顺序存储键值的关联式容器,其允许通过键值快速的索引到对应的元素。在unordered_set中,元素的值同时也是唯一地标识它的key。在内部,unordered_set中的元素没有按照任何特定的顺序排序,为了能在常数范围内找到指定的key,unordered_set将相同哈希值的键值放在相同的桶中。unordered_set容器通过key访问单个元素要比set快,但它通常在遍历元素子集的范围迭代方面效率较低。它的迭代器至少是前向迭代器。前向迭代器的特性。
174 0
|
3月前
|
编译器 C++ 容器
用一棵红黑树同时封装出map和set
再完成上面的代码后,我们的底层代码已经完成了,这时候已经是一个底层STL的红黑树了,已经已符合库里面的要求了,这时候我们是需要给他穿上对应的“衣服”,比如穿上set的“衣服”,那么这个穿上set的“衣服”,那么他就符合库里面set的要求了,同样map一样,这时候我们就需要实现set与map了。因此,上层容器map需要向底层红黑树提供一个仿函数,用于获取T当中的键值Key,这样一来,当底层红黑树当中需要比较两个结点的键值时,就可以通过这个仿函数来获取T当中的键值了。我们就可以使用仿函数了。
41 0
|
3月前
|
存储 编译器 容器
set、map、multiset、multimap的介绍及使用以及区别,注意事项
set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。set默认是升序的,但是其内部默认不是按照大于比较,而是按照小于比较。set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
186 0
|
6月前
|
存储 算法 C++
【c++丨STL】set/multiset的使用
本文深入解析了STL中的`set`和`multiset`容器,二者均为关联式容器,底层基于红黑树实现。`set`支持唯一性元素存储并自动排序,适用于高效查找场景;`multiset`允许重复元素。两者均具备O(logN)的插入、删除与查找复杂度。文章详细介绍了构造函数、迭代器、容量接口、增删操作(如`insert`、`erase`)、查找统计(如`find`、`count`)及`multiset`特有的区间操作(如`lower_bound`、`upper_bound`、`equal_range`)。最后预告了`map`容器的学习,其作为键值对存储的关联式容器,同样基于红黑树,具有高效操作特性。
254 3
|
7月前
|
编译器 容器
哈希表模拟封装unordered_map和unordered_set
哈希表模拟封装unordered_map和unordered_set