C++11 新特性:std::unordered_set 无序集合

std::unordered_set是 C++11 中引入的另一个关联容器(另外一个是上篇文章中介绍的 std::unordered_map),它提供了存储唯一元素的能力。

它内部也是使用哈希表来实现,查找、插入和删除操作的平均时间复杂度为 O(1)。

内部实现

std::unordered_set的内部实现基于哈希表,哈希表是一个数组,数组的每个元素称为一个 bucket。这点和 std::unordered_map 是一样的。

同样的,每个 bucket 维护一个链表(或其他容器,例如小型向量),用于解决哈希冲突(即不同元素的哈希值相同的情况)。

  • 哈希函数std::unordered_set通过哈希函数将元素映射到一个 bucket。哈希函数的质量决定了元素在哈希表中的分布,影响容器的性能。
  • 哈希冲突:当两个元素的哈希值相同时,它们会被存储在同一个 bucket 的链表中,这种情况称为哈希冲突。std::unordered_set通过链地址法来解决哈希冲突。
  • 装载因子和重哈希:装载因子是元素数量与 bucket 数量的比值。当装载因子超过某个阈值时(默认为1.0),std::unordered_set会进行重哈希操作,即增加 bucket 数量并重新分配所有元素,以保持操作的高效性。

使用场景

std::unordered_set适用于以下场景:

  • 需要快速查找的场景:当你需要存储一组唯一元素,并且频繁地进行查找操作时,可以选择std::unordered_set
  • 不关心元素顺序std::unordered_set不保证元素的顺序,如果你不需要元素有序,那么它可以提供比有序容器更好的性能。
  • 大量数据的去重:当需要从大量数据中去除重复项时,std::unordered_set可以高效地完成这个任务。

常用方法

std::unordered_set提供了一系列方法来管理集合中的元素:

  • insert:插入一个新元素到集合中,如果元素已存在,则不会插入。
  • erase:删除集合中的一个元素。
  • find:查找一个元素,返回一个指向找到的元素的迭代器,如果没有找到,则返回end()迭代器。
  • clear:清空集合中的所有元素。
  • size:返回集合中元素的数量。
  • empty:检查集合是否为空。
  • bucket_count:返回当前bucket的数量。
  • load_factor:返回当前装载因子。
  • max_load_factor:获取或设置允许的最大装载因子。

示例代码

以下是一个std::unordered_set的简单使用示例:

#include <iostream>
#include <unordered_set>

int main() {
    std::unordered_set<int> mySet;
    
    std::cout << "Before add elements......" << std::endl;
    std::cout << "Max load facotr: " << mySet.max_load_factor() << std::endl;
    std::cout << "Load factor: " << mySet.load_factor() << std::endl;
    std::cout << "Bucket count: " << mySet.bucket_count() << std::endl;
    std::cout << std::endl;

    // 插入元素
    mySet.insert(1);
    mySet.insert(2);
    mySet.insert(2); // 重复插入,不会有任何效果
    mySet.insert(3);

    // 查找元素
    if (mySet.find(2) != mySet.end()) {
        std::cout << "Found 2 in the set." << std::endl;
    }

    // 遍历集合
    std::cout << "Elements in mySet: ";
    for (int element : mySet) {
        std::cout << element << " ";
    }
    std::cout << std::endl;

    // 删除元素
    mySet.erase(2);
    std::cout << "After erasing 2, size of mySet: " << mySet.size() << std::endl;
    
    std::cout << std::endl;
    std::cout << "After add elements......" << std::endl;
    std::cout << "Max load facotr: " << mySet.max_load_factor() << std::endl;
    std::cout << "Load factor: " << mySet.load_factor() << std::endl;
    std::cout << "Bucket count: " << mySet.bucket_count() << std::endl;

    return 0;
}

输出:

Before add elements......
Max load facotr: 1
Load factor: 0
Bucket count: 1

Found 2 in the set.
Elements in mySet: 3 2 1 
After erasing 2, size of mySet: 2

After add elements......
Max load facotr: 1
Load factor: 0.153846
Bucket count: 13

这里的 Load factor: 0.153846 计算很简单,经过一番操作之后,set 只有 2 个元素,load_factor = 2/13

std::unordered_set 和 std::unordered_map 的区别

unordered_set 和 unordered_map 都是基于哈希表的容器,提供快速的查找、插入和删除操作。它们在内部实现上相似,主要用于高效存储和管理数据。

它们的区别体现在数据组织方式和用途上。

  • 数据结构std::unordered_set存储的是一组无序的唯一元素,只有 Key;而std::unordered_map存储的是键值对 Key-Value,其中键是唯一的。

  • 用途:如果你需要一个不允许重复的元素集合,并且只关心元素是否存在,选择std::unordered_set。如果你需要存储关联数据,如每个元素(键)都有一个特定的值,那么std::unordered_map则更合适。

总结

std::unordered_set是 C++11 中引入的基于哈希表的集合容器,它支持快速的元素查找、插入和删除操作。

理解std::unordered_set的内部实现可以帮助开发者更有效地使用它,特别是在需要高效管理一组唯一元素的场景下。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值