C++中set集合和Python中set集合的区别

devtools/2024/10/18 4:09:07/

C++ 和 Python 中的 set 容器都有相同的集合属性:元素唯一性和常规的集合操作(如交集、并集、差集等),但由于它们的实现机制、操作方法和性能特性有所不同,适用场景也存在差异。以下是两者的主要区别:

1. 底层实现

  • C++ set

    • 使用**红黑树(Red-Black Tree)**实现,因此它是有序集合,默认情况下,所有元素按升序排列。
    • 插入、删除和查找的时间复杂度为 O(log n)
    • C++ 中还提供了 unordered_set,它使用哈希表实现,提供 O(1) 的查找和插入性能,但元素是无序的。
  • Python set

    • 使用**哈希表(Hash Table)**实现,是无序集合,元素的存储顺序不一定与插入顺序一致。
    • 插入、删除和查找的时间复杂度平均为 O(1)
    • 由于哈希表的特性,元素必须是可哈希的(支持 __hash__ 方法),通常需要是不可变类型(如整数、字符串、元组等)。

2. 元素类型及可变性

  • C++ set

    • 元素类型由模板参数指定,如 set<int> 表示存储整型元素的集合。
    • 可以存储任何可以进行比较的自定义类型(需要实现 < 操作符),如结构体、自定义类等。
    • 元素在 set 中通常是不可变的,因为修改元素可能破坏有序性,若需要修改元素,需要先删除后插入。
  • Python set

    • 可以存储任意类型的元素,只要它们是可哈希的。
    • 可以混合不同类型的数据,但必须保证类型是可比较和可哈希的。
    • 元素本身不可变,但集合本身是可变的,可以动态添加或删除元素。

3. 性能差异

  • C++ set

    • 由于 set 基于红黑树实现,因此插入、删除、查找的时间复杂度是 O(log n),比哈希表实现的 Python set 稍慢,但能保持元素有序。
    • 适合需要元素有序访问的场景,且元素个数较大时(上万或以上)性能相对稳定。
  • Python set

    • 基于哈希表实现,插入、删除、查找的平均时间复杂度为 O(1),性能非常高,但在元素较多或哈希冲突严重时,性能可能下降。
    • 适合快速查找、去重和集合操作,但不适合需要排序的场景。

4. 有序性

  • C++ set

    • 默认按升序存储元素,也可以通过自定义比较函数实现自定义排序规则(如降序排列)。
    • 提供了 multiset 容器,可以存储重复元素,并且依然保持有序性。
  • Python set

    • 元素无序存储,且集合操作(如交集、并集、差集等)的结果顺序不一定固定。
    • 如果需要存储有序集合,可以使用 sorted() 函数对 set 进行排序,或者使用 collections.OrderedDict 来实现类似功能。

5. 成员函数与操作符

  • C++ set

    • 提供了丰富的成员函数(如 inserterasefindcountlower_boundupper_bound 等)用于操作集合。
    • 支持标准的集合操作(如交集、并集、差集等),但需要使用算法库 <algorithm> 中的函数(如 std::set_intersection 等)。
  • Python set

    • 提供了更加直观的操作符(如 & 表示交集、| 表示并集、- 表示差集、^ 表示对称差集)和方法(如 addremovediscardpopunionintersection 等)。
    • 操作符和方法更加直观简洁,适合快速开发和原型设计。

6. 常用操作对比

以下是 C++ set 和 Python set 的一些常用操作对比:

操作C++ setPython set
创建集合std::set<int> s;s = set()
插入元素s.insert(10);s.add(10)
删除元素s.erase(10);s.remove(10) / s.discard(10)
查找元素s.find(10) != s.end()10 in s
交集std::set<int> s3; std::set_intersection(s.begin(), s.end(), s2.begin(), s2.end(), std::inserter(s3, s3.begin()));s & s2
并集std::set<int> s3; std::set_union(s.begin(), s.end(), s2.begin(), s2.end(), std::inserter(s3, s3.begin()));`s
差集std::set<int> s3; std::set_difference(s.begin(), s.end(), s2.begin(), s2.end(), std::inserter(s3, s3.begin()));s - s2
对称差集std::set<int> s3; std::set_symmetric_difference(s.begin(), s.end(), s2.begin(), s2.end(), std::inserter(s3, s3.begin()));s ^ s2

7. 内存管理

  • C++ set

    • 元素分配使用标准的动态内存分配器,如 std::allocator,可以根据需求自定义内存分配策略。
    • 由于 set 的元素存储在树的节点中,因此内存开销略大于 vectorlist 等线性容器。
  • Python set

    • 元素直接存储在哈希表中,因此哈希表的负载因子(load factor)决定了内存使用量。
    • 由于哈希表本身的存储结构,内存开销较高,但可以快速进行查找操作。

8. 特殊类型集合

  • C++ set

    • 提供了 multiset(可以存储重复元素),以及 unordered_set(基于哈希表实现,无序集合)。
    • 也有 unordered_multiset,用于存储重复元素的无序集合。
  • Python set

    • 提供了 frozenset,即不可变集合,常用于集合作为其他集合或字典的键(因为普通 set 是可变类型,不能作为字典的键)。
    • 没有类似 multiset 的类型(可以使用 collections.Counter 来实现重复元素的集合统计)。

总结

  • 如果你需要有序集合或需要处理复杂的集合操作(如排序、区间查找等),C++ 的 set 更加合适。
  • 如果你需要快速查找、插入、删除操作,且不关注元素的存储顺序,Python 的 set 更为合适。

http://www.ppmy.cn/devtools/119805.html

相关文章

【C语言】指针详解(一)

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1.内存与地址2.指针变量与地址2.1 取地址操作符&2.2 指针变量2.3 指针类型2.4 解引用操作符2.5 指针变量的大小 3. 指针变量类型的意义3.1 指针的解引用 4. const修饰指针4.1 const修饰变量4.2 const修饰指针变量…

OpenCV视频I/O(3)视频采集类VideoCapture之获取当前使用的视频捕获 API 后端的名称函数getBackendName()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 getBackendName 函数是 OpenCV 中 VideoCapture 类的一个方法&#xff0c;用于获取当前使用的视频捕获 API 后端的名称。这可以帮助开发者了解当…

初识Linux · 进程等待

目录 前言&#xff1a; 进程等待是什么 为什么需要进程等待 进程等待都在做什么 前言&#xff1a; 通过上文的学习&#xff0c;我们了解了进程终止&#xff0c;知道终止是在干什么&#xff0c;终止的三种情况&#xff0c;以及有了退出码&#xff0c;错误码的概念&#xff…

UE4_Niagara基础实例—5、骨架网格体表面生成粒子及过滤骨骼位置生成粒子

效果图&#xff1a; 步骤&#xff1a; 1、学习了静态网格体位置生成粒子之后这个就比较简单了&#xff0c;把粒子生成位置更改为SkeletalMeshLocation。 2、小白人的骨骼网格体为&#xff1a; 你会发现骨骼的每一个节点处都有粒子产生。 3、我们还可以修改骨骼采样类型 4、我们…

HTML·第三章课后练习题

采用表格布局完成“CASIO计算器”外观设计&#xff0c;其中表格的每一个单元格均需要设计带边框 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width…

python单例和工厂模式

设计模式 设计模式是一种编程套路&#xff0c;可以极大的方便程序的开发 最常见、最经典的设计模式&#xff0c;就是学习的面向对象 除了面向对象之外&#xff0c;在编程中也有很多既定的套路可以方便开发&#xff0c;我们称之为设计模式&#xff1a; 单例、工厂模式建造者…

Redis篇(缓存机制 - 多级缓存)(持续更新迭代)

目录 一、传统缓存的问题 二、JVM进程缓存 1. 导入案例 2. 初识Caffeine 3. 实现JVM进程缓存 3.1. 需求 3.2. 实现 三、Lua语法入门 1. 初识Lua 2. HelloWorld 3. 变量和循环 3.1. Lua的数据类型 3.2. 声明变量 3.3. 循环 4. 条件控制、函数 4.1. 函数 4.2. 条…

极狐GitLab 17.4 重点功能解读【一】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…