Z
ZHANK
数据结构

集合 (Set)

学习集合去重特性、交集并集运算、成员快速判断

集合 (Set)

集合是无序、不重复的元素集合,和数学中的集合概念完全一致。它是去重和成员检查的利器。

学完本章你将掌握: 创建、集合运算、去重、成员检查、冰冻集合。


一、创建集合

python
# 花括号创建
fruits = {"苹果", "香蕉", "橘子"}

# set() 构造函数(从列表去重的好方法)
nums = set([1, 2, 2, 3, 3, 3, 4])
print(nums)  # {1, 2, 3, 4}  自动去重!

# 空集合只能用 set(),{} 是空字典!
s = set()
print(type(s))  # <class 'set'>
print(type({})) # <class 'dict'>  ← 注意!

二、集合运算

python
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

print(f"交集: {a & b}")        # {3, 4}
print(f"并集: {a | b}")        # {1, 2, 3, 4, 5, 6}
print(f"差集: {a - b}")        # {1, 2}(a有b没有)
print(f"差集: {b - a}")        # {5, 6}(b有a没有)
print(f"对称差: {a ^ b}")      # {1, 2, 5, 6}(只在一边的)

# 也可以用方法实现同样操作
print(a.intersection(b))
print(a.union(b))

三、增删元素

python
s = {1, 2, 3}

s.add(4)          # 添加
s.add(2)          # 已存在,不会重复

s.remove(3)       # 删除(元素不存在报 KeyError)
s.discard(5)      # 安全删除(不存在也不报错)

popped = s.pop()  # 随机删除一个(集合无序)

四、成员检查

集合的 in 是 O(1),比列表快很多:

python
# 模拟:检查 10000 个 ID 是否在白名单中
whitelist = set(range(0, 10000, 2))  # 5000 个偶数
check_ids = range(10000)

count = 0
for n in check_ids:
    if n in whitelist:  # O(1) 超快!
        count += 1
print(f"命中: {count}")  # 5000

💡 集合 vs 列表:做成员检查时,集合是 O(1),列表是 O(n)。数据量大时差距巨大。


五、去重实战

python
# 场景:统计访问过网站的用户(自动去重)
visitors = set()
visitors.add("小明")
visitors.add("小红")
visitors.add("小明")  # 重复,自动忽略
visitors.add("小刚")
print(visitors)       # {'小明', '小红', '小刚'}
print(len(visitors))  # 3(去重后的数量)

# 列表去重并保留顺序
items = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]
unique = list(dict.fromkeys(items))  # Python 3.7+ 字典保序
print(unique)  # [3, 1, 4, 5, 9, 2, 6]

六、集合推导式

python
# 和列表推导式语法一样,用 {} 而不是 []
squares = {x**2 for x in range(10)}
print(squares)  # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}

# 带条件
evens = {x for x in range(20) if x % 2 == 0}
print(evens)  # {0, 2, 4, 6, 8, 10, 12, 14, 16, 18}

七、frozenset(不可变集合)

python
# 普通集合:可变,不能作字典键
s = {1, 2, 3}
# d = {s: "value"}  # ❌ TypeError: unhashable type: 'set'

# frozenset:不可变,可以作字典键
fs = frozenset([1, 2, 3])
d = {fs: "value"}
print(d[fs])  # value

八、集合的子集/超集

python
a = {1, 2}
b = {1, 2, 3, 4}

print(a.issubset(b))     # True(a是b的子集)
print(b.issuperset(a))   # True(b包含a)
print(a <= b)            # True(等价于 issubset)
print(b >= a)            # True(等价于 issuperset)

小结

  1. 集合自动去重,元素不可重复
  2. &(交)、|(并)、-(差)、^(对称差)
  3. add() remove() discard() 增删元素
  4. in 检查是 O(1),比列表快很多
  5. frozenset 是不可变版本,可作字典键

小练习

  1. 用集合给 [1,2,2,3,3,3,4,4,4,4] 去重
  2. 找出两个列表 [1,2,3,4][3,4,5,6] 的交集和并集
  3. 判断 {1,2} 是不是 {1,2,3,4} 的子集

💬 下一章预告:接下来学习输入与输出——让程序和用户互动。