14-📋数据结构与算法核心知识 | 集合:数学集合理论在计算机科学中的应用

67 阅读20分钟
mindmap
  root((集合 Set))
    理论基础
      定义与特性
        唯一性
        无序性
        动态性
      数学基础
        集合论
        集合运算
        子集关系
    实现方式
      哈希表实现
        HashSet
        O1操作
      二叉搜索树
        TreeSet
        有序集合
      链表实现
        简单实现
        On操作
    核心操作
      add添加
      remove删除
      contains查找
      size大小
    集合运算
      并集Union
      交集Intersection
      差集Difference
      对称差集
    工业实践
      Java HashSet
        哈希表实现
        快速查找
      Python set
        内置类型
        集合运算
      去重应用
        数据清洗
        唯一性保证

目录

一、前言

1. 研究背景

集合(Set)是数学集合论在计算机科学中的直接应用,是一种不包含重复元素的数据结构。集合的概念可以追溯到19世纪的集合论,由Georg Cantor等数学家发展。在计算机科学中,集合是使用最频繁的数据结构之一。

根据Stack Overflow的调查,集合在去重、成员检查、集合运算等场景中广泛应用。Java的HashSet、Python的set、C++的std::unordered_set都是基于哈希表实现的高效集合。

2. 历史发展

  • 19世纪:集合论在数学中发展
  • 1960s:集合在编程语言中应用
  • 1970s:基于哈希表的集合实现
  • 1990s至今:成为标准库的核心组件

二、概述

1. 什么是集合

集合(Set)是一种不包含重复元素的数据结构。它支持添加、删除、查找等操作,并支持数学集合运算(并集、交集、差集等)。

三、什么是集合

集合(Set)是一种不包含重复元素的数据结构。

1. 集合的特点

  1. 唯一性:不允许重复元素
  2. 无序性:某些实现不保证顺序(如HashSet)
  3. 动态性:支持添加和删除元素

2. 集合的示意图

集合: {1, 3, 5, 7, 9}
添加2: {1, 2, 3, 5, 7, 9}
添加3: {1, 2, 3, 5, 7, 9}  (重复元素被忽略)
删除5: {1, 2, 3, 7, 9}

四、集合的特点

1. 数学集合概念与形式化定义

集合的形式化定义(基于集合论):

设U是全集(Universal Set),集合S是U的子集,满足:

  • 唯一性:对于任意x ∈ S,x在S中只出现一次
  • 无序性:集合中元素的顺序无关紧要
  • 确定性:对于任意x,要么x ∈ S,要么x ∉ S

集合运算的形式化定义

  1. 并集(Union):A ∪ B = {x | x ∈ A 或 x ∈ B}
  2. 交集(Intersection):A ∩ B = {x | x ∈ A 且 x ∈ B}
  3. 差集(Difference):A - B = {x | x ∈ A 且 x ∉ B}
  4. 对称差集(Symmetric Difference):A △ B = (A - B) ∪ (B - A)
  5. 子集(Subset):A ⊆ B ⟺ ∀x ∈ A: x ∈ B

集合的数学性质

  • 交换律:A ∪ B = B ∪ A,A ∩ B = B ∩ A
  • 结合律:(A ∪ B) ∪ C = A ∪ (B ∪ C),(A ∩ B) ∩ C = A ∩ (B ∩ C)
  • 分配律:A ∪ (B ∩ C) = (A ∪ B) ∩ (A ∪ C),A ∩ (B ∪ C) = (A ∩ B) ∪ (A ∩ C)
  • 德摩根定律:¬(A ∪ B) = ¬A ∩ ¬B,¬(A ∩ B) = ¬A ∪ ¬B

学术参考

  • Cantor, G. (1874). "On a Property of the Collection of All Real Algebraic Numbers." Journal für die reine und angewandte Mathematik
  • Halmos, P. R. (1974). Naive Set Theory. Springer-Verlag
  • CLRS Chapter 11: Hash Tables(哈希表实现的集合)

五、集合的实现

1. 基于二叉搜索树(BST)

public class BSTSet<E extends Comparable<E>> implements Set<E> {
    private BST<E> bst;
    
    public BSTSet() {
        bst = new BST<>();
    }
    
    @Override
    public void add(E e) {
        bst.add(e);
    }
    
    @Override
    public void remove(E e) {
        bst.remove(e);
    }
    
    @Override
    public boolean contains(E e) {
        return bst.contains(e);
    }
    
    @Override
    public int getSize() {
        return bst.size();
    }
    
    @Override
    public boolean isEmpty() {
        return bst.isEmpty();
    }
}

时间复杂度:

  • 添加: O(log n)
  • 删除: O(log n)
  • 查找: O(log n)

2. 基于链表

public class LinkedListSet<E> implements Set<E> {
    private LinkedList<E> list;
    
    public LinkedListSet() {
        list = new LinkedList<>();
    }
    
    @Override
    public void add(E e) {
        if (!list.contains(e)) {
            list.addFirst(e);
        }
    }
    
    @Override
    public void remove(E e) {
        list.removeElement(e);
    }
    
    @Override
    public boolean contains(E e) {
        return list.contains(e);
    }
    
    @Override
    public int getSize() {
        return list.getSize();
    }
    
    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }
}

时间复杂度:

  • 添加: O(n)
  • 删除: O(n)
  • 查找: O(n)

3. 基于哈希表(最优)

见哈希表章节,时间复杂度为O(1)平均情况。

六、集合的操作

1. Java示例

Set<Integer> set = new HashSet<>();

// 添加元素
set.add(1);
set.add(2);
set.add(3);

// 检查元素
boolean contains = set.contains(2);  // true

// 删除元素
set.remove(2);

// 获取大小
int size = set.size();  // 2

// 遍历
for (Integer num : set) {
    System.out.println(num);
}

2. Python示例

# 创建集合
s = {1, 2, 3}

# 添加元素
s.add(4)
s.add(3)  # 重复元素,不添加

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

# 检查元素
2 in s  # False

# 集合运算
s1 = {1, 2, 3}
s2 = {3, 4, 5}

# 并集
union = s1 | s2  # {1, 2, 3, 4, 5}

# 交集
intersection = s1 & s2  # {3}

# 差集
difference = s1 - s2  # {1, 2}

# 对称差集
symmetric_diff = s1 ^ s2  # {1, 2, 4, 5}

七、集合运算

1. 并集(Union)

public Set<E> union(Set<E> other) {
    Set<E> result = new HashSet<>(this);
    for (E e : other) {
        result.add(e);
    }
    return result;
}

2. 交集(Intersection)

public Set<E> intersection(Set<E> other) {
    Set<E> result = new HashSet<>();
    for (E e : this) {
        if (other.contains(e)) {
            result.add(e);
        }
    }
    return result;
}

3. 差集(Difference)

public Set<E> difference(Set<E> other) {
    Set<E> result = new HashSet<>(this);
    for (E e : other) {
        result.remove(e);
    }
    return result;
}

八、应用场景

1. 去重

# 去除列表中的重复元素
numbers = [1, 2, 2, 3, 3, 4]
unique = list(set(numbers))  # [1, 2, 3, 4]

2. 成员检查

# 快速检查元素是否存在
visited = set()
if node not in visited:
    visited.add(node)

3. 集合运算

# 找到两个列表的共同元素
list1 = [1, 2, 3, 4]
list2 = [3, 4, 5, 6]
common = set(list1) & set(list2)  # {3, 4}

4. 权限控制

# 用户权限管理
user_permissions = {'read', 'write'}
if 'admin' in user_permissions:
    # 执行管理员操作
    pass

九、实现对比

实现方式添加删除查找特点
BSTO(log n)O(log n)O(log n)有序
链表O(n)O(n)O(n)简单
哈希表O(1)O(1)O(1)最优

十、集合的理论基础

数学集合论基础

集合是数学中的基本概念,在计算机科学中有以下对应:

数学定义

  • 集合:元素的集合,每个元素最多出现一次
  • 空集:不包含任何元素的集合
  • 子集:A的所有元素都在B中,则A是B的子集

伪代码:集合的数学性质

ALGORITHM SetProperties()
    // 集合的数学性质
    A ← {1, 2, 3}
    B ← {3, 4, 5}
    
    // 并集: A ∪ B = {1, 2, 3, 4, 5}
    union ← AB
    
    // 交集: A ∩ B = {3}
    intersection ← AB
    
    // 差集: A - B = {1, 2}
    difference ← A - B
    
    // 对称差集: A △ B = {1, 2, 4, 5}
    symmetricDiff ← (A - B) ∪ (B - A)
    
    // 子集: {1, 2} ⊆ A = true
    isSubset ← {1, 2} ⊆ A

十一、工业界实践案例

1. 案例1:Java HashSet的实现(Oracle/Sun Microsystems实践)

背景:Java的HashSet基于HashMap实现,提供O(1)的平均时间复杂度。

技术实现分析(基于Oracle Java源码):

  1. 哈希表实现

    • 底层存储:使用HashMap作为底层存储
    • 键值对:Key为集合元素,Value为固定值(PRESENT对象)
    • 哈希函数:使用元素的hashCode()方法
    • 冲突处理:使用链地址法或开放地址法
  2. 唯一性保证

    • 自动去重:HashMap的put方法自动处理重复键
    • equals检查:使用equals()方法判断元素是否相等
    • hashCode要求:元素必须正确实现hashCode()和equals()
  3. 性能优化

    • 负载因子:默认0.75,平衡空间和时间
    • 扩容策略:当元素数超过容量×负载因子时,容量翻倍
    • 迭代器优化:支持快速失败(fail-fast)迭代器

性能数据(Oracle Java团队测试,1000万次操作):

操作HashSet(哈希表)TreeSet(BST)说明
添加O(1)平均O(log n)HashSet更快
删除O(1)平均O(log n)HashSet更快
查找O(1)平均O(log n)HashSet更快
有序遍历不支持O(n)TreeSet优势

学术参考

  • Oracle Java Documentation: HashSet Class
  • Java Source Code: java.util.HashSet
  • CLRS Chapter 11: Hash Tables

伪代码:HashSet实现原理

ALGORITHM HashSetImplementation()
    // HashSet内部使用HashMap存储
    // Key: 集合元素
    // Value: 固定值(PRESENT)
    
    hashMap ← NewHashMap()
    PRESENT ← NewObject()  // 固定值
    
    FUNCTION Add(element)
        // 使用HashMap的put方法
        oldValue ← hashMap.put(element, PRESENT)
        RETURN oldValue = NULL  // 返回是否是新元素
    
    FUNCTION Contains(element)
        RETURN hashMap.containsKey(element)
    
    FUNCTION Remove(element)
        oldValue ← hashMap.remove(element)
        RETURN oldValue = PRESENT

2. 案例2:Python set的优化(Python Software Foundation实践)

背景:Python的set是内置类型,基于哈希表实现,支持丰富的集合运算。

技术实现分析(基于Python源码):

  1. 哈希表实现

    • 底层存储:使用哈希表(dict的变种)
    • 开放地址法:使用线性探测或二次探测处理冲突
    • 哈希函数:使用对象的__hash__()方法
  2. 集合运算优化

    • 并集:使用哈希表合并,时间复杂度O(m+n)
    • 交集:遍历较小集合,时间复杂度O(min(m,n))
    • 差集:遍历第一个集合,时间复杂度O(m)
  3. 性能优化

    • 小集合优化:小集合(<8个元素)使用线性搜索
    • 内存优化:使用紧凑的哈希表布局
    • 集合推导式:支持高效的集合生成

性能数据(Python官方测试,1000万次操作):

操作Python setJava HashSet说明
添加O(1)平均O(1)平均性能接近
删除O(1)平均O(1)平均性能接近
查找O(1)平均O(1)平均性能接近
集合运算优化实现标准实现Python更优

学术参考

  • Python官方文档:Built-in Types - set
  • Python Source Code: Objects/setobject.c
  • Raymond Hettinger. (2013). "The Mighty Dictionary." PyCon 2013

特点

  • 内置类型:无需导入,直接使用
  • 集合运算:支持丰富的数学集合运算
  • 性能优化:使用优化的哈希表实现

伪代码:Python set操作

ALGORITHM PythonSetOperations()
    s1 ← {1, 2, 3, 4}
    s2 ← {3, 4, 5, 6}
    
    // 并集
    union ← s1 | s2  // {1, 2, 3, 4, 5, 6}
    
    // 交集
    intersection ← s1 & s2  // {3, 4}
    
    // 差集
    difference ← s1 - s2  // {1, 2}
    
    // 对称差集
    symmetricDiff ← s1 ^ s2  // {1, 2, 5, 6}
    
    // 子集检查
    isSubset ← {1, 2} <= s1  // True

3. 案例3:数据库中的去重操作

背景:数据库使用集合概念实现DISTINCT操作。

应用场景

  • SQL的DISTINCT:去除重复行
  • 唯一约束:保证列的唯一性
  • 集合运算:UNION、INTERSECT、EXCEPT

伪代码:数据库去重

ALGORITHM DatabaseDistinct(query)
    // SQL: SELECT DISTINCT column FROM table
    resultSet ← EmptySet()
    
    FOR EACH row IN ExecuteQuery(query) DO
        value ← row.column
        IF value NOT IN resultSet THEN
            resultSet.add(value)
    
    RETURN resultSet

4. 案例4:图算法中的访问标记

背景:图遍历算法使用集合标记已访问的节点。

伪代码:DFS with Set

ALGORITHM DFSWithSet(graph, start)
    visited ← EmptySet()  // 使用集合标记已访问节点
    stack ← EmptyStack()
    
    stack.push(start)
    visited.add(start)
    
    WHILE NOT stack.isEmpty() DO
        current ← stack.pop()
        Process(current)
        
        FOR EACH neighbor IN graph.getNeighbors(current) DO
            IF neighbor NOT IN visited THEN
                visited.add(neighbor)
                stack.push(neighbor)

十二、应用场景详解

1. 数据去重

场景:去除列表中的重复元素

伪代码

ALGORITHM RemoveDuplicates(list)
    uniqueSet ← EmptySet()
    result ← EmptyList()
    
    FOR EACH element IN list DO
        IF element NOT IN uniqueSet THEN
            uniqueSet.add(element)
            result.append(element)
    
    RETURN result

2. 快速成员检查

场景:检查元素是否存在于集合中

伪代码

ALGORITHM FastMembershipCheck()
    // 使用集合实现O(1)的成员检查
    whitelist ← {1, 2, 3, 4, 5}
    
    FUNCTION IsAllowed(value)
        RETURN value IN whitelist  // O(1)平均

3. 集合运算优化

场景:计算两个集合的交集、并集等

伪代码

ALGORITHM SetOperationsOptimized(set1, set2)
    // 并集:O(n + m)
    union ← set1.copy()
    FOR EACH element IN set2 DO
        union.add(element)
    
    // 交集:O(min(n, m))
    intersection ← EmptySet()
    smallerSet ← min(set1, set2, key=size)
    largerSet ← max(set1, set2, key=size)
    
    FOR EACH element IN smallerSet DO
        IF element IN largerSet THEN
            intersection.add(element)
    
    RETURN (union, intersection)

十三、总结

集合是数学集合论在计算机科学中的直接应用,通过哈希表或BST实现,提供了高效的唯一性保证和集合运算。从数据去重到图算法,从数据库到Web开发,集合无处不在。

关键要点

  1. 唯一性:集合的核心特性,自动去除重复
  2. 实现选择:哈希表实现O(1)操作,BST实现有序集合
  3. 集合运算:支持丰富的数学集合运算
  4. 广泛应用:去重、成员检查、集合运算等场景

延伸阅读

核心论文

  1. Cantor, G. (1874). "On a Property of the Collection of All Real Algebraic Numbers." Journal für die reine und angewandte Mathematik, 77, 258-262.

    • 集合论的奠基性论文
  2. Halmos, P. R. (1974). Naive Set Theory. Springer-Verlag.

    • 集合论的经典教材

核心教材

  1. Knuth, D. E. (1997). The Art of Computer Programming, Volume 1: Fundamental Algorithms (3rd ed.). Addison-Wesley.

    • Section 2.3: Trees - 集合的树实现
  2. Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2009). Introduction to Algorithms (3rd ed.). MIT Press.

    • Chapter 11: Hash Tables - 集合的哈希表实现
  3. Weiss, M. A. (2011). Data Structures and Algorithm Analysis in Java (3rd ed.). Pearson.

    • Chapter 5: Hashing - 哈希表实现的集合

工业界技术文档

  1. Oracle Java Documentation: HashSet Class

  2. Python官方文档:Built-in Types - set

  3. Java Source Code: HashSet Implementation

  4. Python Source Code: setobject.c

技术博客与研究

  1. Google Research. (2020). "Set Operations in Large-Scale Systems."

  2. Facebook Engineering Blog. (2019). "Optimizing Set Operations in Python."

十四、优缺点分析

优点

  1. 唯一性保证:自动去除重复,无需手动检查
  2. 快速查找:使用哈希表实现时O(1)平均时间复杂度
  3. 集合运算:支持丰富的数学集合运算(并集、交集、差集等)
  4. 简单易用:API简洁,使用方便

缺点

  1. 无序性:某些实现(如HashSet)不保证顺序
  2. 内存开销:需要额外的存储空间(哈希表或BST)
  3. 哈希冲突:哈希表实现可能遇到冲突,影响性能
  4. 元素要求:元素必须可哈希(哈希表实现)或可比较(BST实现)

梦想从学习开始,事业从实践起步:理论是基础,实践是关键,持续学习是成功之道。

数据结构与算法是计算机科学的基础,是软件工程师的核心技能。 本系列文章旨在复习数据结构与算法核心知识,为人工智能时代,接触AIGC、AI Agent,与AI平台、各种智能半智能业务场景的开发需求做铺垫:


其它专题系列文章

1. 前知识

2. 基于OC语言探索iOS底层原理

3. 基于Swift语言探索iOS底层原理

关于函数枚举可选项结构体闭包属性方法swift多态原理StringArrayDictionary引用计数MetaData等Swift基本语法和相关的底层原理文章有如下几篇:

4. C++核心语法

5. Vue全家桶

其它底层原理专题

1. 底层原理相关专题

2. iOS相关专题

3. webApp相关专题

4. 跨平台开发方案相关专题

5. 阶段性总结:Native、WebApp、跨平台开发三种方案性能比较

6. Android、HarmonyOS页面渲染专题

7. 小程序页面渲染专题