了解一下C#的SortedSet

基础概念

SortedSet 是 C# 中的一个集合类型,位于 System.Collections.Generic 命名空间下。它是一个自动排序的集合,用于存储不重复的元素,并且会根据元素的自然顺序(默认排序)或自定义比较器进行排序,内部使用红黑树数据结构来维护元素的有序性。

  • 自动排序:每次添加或删除元素时,SortedSet 都会自动调整以保持元素的排序状态。
  • 不重复元素:SortedSet 不允许重复的元素。如果尝试添加一个已经存在的元素,该操作会被忽略。
  • 高效性 :SortedSet 内部使用红黑树 (一种自平衡二叉搜索树)实现,因此查找、插入和删除操作的时间复杂度为 O(log n)

主要特性

  • 自动保持元素排序:元素会根据其自然顺序(需实现 IComparable<T> 接口)或自定义比较器(IComparer<T>)排序。
  • 不包含重复元素:尝试添加已有元素时,Add 方法返回 false,集合保持不变。
  • 支持集合操作:提供并集、交集、差集等操作。
  • 支持子集视图:可以通过方法获取某个范围内的元素。
  • 快速访问边界值:提供 Min 和 Max 属性,快速获取最小和最大元素。

创建和初始化

基本创建方式

  • 使用默认比较器(升序)
    *

    cs 复制代码
    // 使用默认比较器(升序)
    SortedSet<int> numbers = new SortedSet<int>();
  • 使用自定义比较器
    *

    cs 复制代码
    // 使用自定义比较器
    SortedSet<string> names = new SortedSet<string>(StringComparer.OrdinalIgnoreCase);
  • 从现有集合创建
    *

    cs 复制代码
    // 从现有集合创建
    int[] array = { 5, 2, 8, 1, 9 };
    SortedSet<int> sortedNumbers = new SortedSet<int>(array);
    // 结果:{1, 2, 5, 8, 9}
  • 使用集合初始化器
    *

    cs 复制代码
    // 使用集合初始化器
    SortedSet<string> fruits = new SortedSet<string> { "Apple", "Banana", "Cherry" };

自定义比较器

  • 降序排列
    *

    cs 复制代码
    // 降序排列
    SortedSet<int> descendingNumbers = new SortedSet<int>(Comparer<int>.Create((x, y) => y.CompareTo(x)));
  • 自定义对象排序
    *

    cs 复制代码
    // 自定义对象排序
    public class Person : IComparable<Person>
    {
        public string Name { get; set; }
        public int Age { get; set; }
        
        public int CompareTo(Person other)
        {
            if (other == null) return 1;
            return this.Age.CompareTo(other.Age); // 按年龄排序
        }
    }
    
    SortedSet<Person> people = new SortedSet<Person>();
  • 使用自定义比较器
    *

    cs 复制代码
    // 或使用自定义比较器
    SortedSet<Person> peopleByName = new SortedSet<Person>(
        Comparer<Person>.Create((p1, p2) => string.Compare(p1.Name, p2.Name))
    );

基本操作

添加和删除元素

cs 复制代码
SortedSet<int> numbers = new SortedSet<int>();
  • 添加元素
    *

    cs 复制代码
    // 添加元素
    bool added1 = numbers.Add(5);    // true,成功添加
    bool added2 = numbers.Add(3);    // true,成功添加
    bool added3 = numbers.Add(5);    // false,元素已存在
    
    Console.WriteLine(string.Join(", ", numbers)); // 输出:3, 5
  • 删除元素
    *

    cs 复制代码
    // 删除元素
    bool removed = numbers.Remove(3); // true,成功删除
    numbers.Remove(10);  
  • 清空集合
    *

    cs 复制代码
    // 清空集合
    numbers.Clear();

查询操作

cs 复制代码
SortedSet<int> numbers = new SortedSet<int> { 1, 3, 5, 7, 9 };
  • 检查元素是否存在
    *

    cs 复制代码
    // 检查元素是否存在
    bool contains = numbers.Contains(5); // true
  • 获取元素数量
    *

    cs 复制代码
    // 获取元素数量
    int count = numbers.Count; // 5
  • 检查是否为空
    *

    cs 复制代码
    // 检查是否为空
    bool isEmpty = numbers.Count == 0; // false
  • 获取最小值和最大值
    *

    cs 复制代码
    // 获取最小值和最大值
    int min = numbers.Min; // 1
    int max = numbers.Max; // 9

范围查询

  • 使用 GetViewBetween 方法获取指定范围内的元素子集
cs 复制代码
SortedSet<int> numbers = new SortedSet<int> { 1, 3, 5, 7, 9, 11, 13 };

// 获取视图(不创建新集合)
SortedSet<int> subset1 = numbers.GetViewBetween(3, 9);
// 结果:{3, 5, 7, 9}

SortedSet<int> subset2 = numbers.GetViewBetween(4, 10);
// 结果:{5, 7, 9}

// 视图会反映原集合的变化
numbers.Add(6);
Console.WriteLine(string.Join(", ", subset2)); // 输出:5, 6, 7, 9

集合运算

并集、交集、差集

cs 复制代码
SortedSet<int> set1 = new SortedSet<int> { 1, 2, 3, 4, 5 };
SortedSet<int> set2 = new SortedSet<int> { 4, 5, 6, 7, 8 };
  • 并集: UnionWith 将另一个集合的元素合并到 SortedSet 中。
    *

    cs 复制代码
    // 并集(修改 set1)
    set1.UnionWith(set2);
    Console.WriteLine(string.Join(", ", set1)); // 1, 2, 3, 4, 5, 6, 7, 8
  • 交集: IntersectWith 保留与另一个集合的交集。
    *

    cs 复制代码
    // 重新初始化
    set1 = new SortedSet<int> { 1, 2, 3, 4, 5 };
    
    // 交集(修改 set1)
    set1.IntersectWith(set2);
    Console.WriteLine(string.Join(", ", set1)); // 4, 5
  • 差集: ExceptWith 删除与另一个集合相交的元素。
    *

    cs 复制代码
    // 重新初始化
    set1 = new SortedSet<int> { 1, 2, 3, 4, 5 };
    
    // 差集(set1 中有但 set2 中没有的元素)
    set1.ExceptWith(set2);
    Console.WriteLine(string.Join(", ", set1)); // 1, 2, 3
  • 对称差集: SymmetricExceptWith 两个集合中不共同拥有的元素
    *

    cs 复制代码
    // 对称差集(两个集合中不共同拥有的元素)
    set1 = new SortedSet<int> { 1, 2, 3, 4, 5 };
    set1.SymmetricExceptWith(set2);
    Console.WriteLine(string.Join(", ", set1)); // 1, 2, 3, 6, 7, 8

集合关系判断

cs 复制代码
SortedSet<int> set1 = new SortedSet<int> { 1, 2, 3 };
SortedSet<int> set2 = new SortedSet<int> { 1, 2, 3, 4, 5 };
SortedSet<int> set3 = new SortedSet<int> { 2, 3 };
SortedSet<int> set4 = new SortedSet<int> { 6, 7 };
  • 子集判断
    *

    cs 复制代码
    // 子集判断
    
    bool isSubset = set1.IsSubsetOf(set2);        // true
    bool isProperSubset = set1.IsProperSubsetOf(set2); // true
    bool isSuperset = set2.IsSupersetOf(set1);    // true
    bool isProperSuperset = set2.IsProperSupersetOf(set1); // true
  • 重叠判断
    *

    cs 复制代码
    // 重叠判断
    bool overlaps = set1.Overlaps(set3);          // true(有共同元素2,3)
    bool overlaps2 = set1.Overlaps(set4);         // false(无共同元素)
  • 相等判断
    *

    cs 复制代码
    // 相等判断
    bool areEqual = set1.SetEquals(set3);         // false

遍历和枚举

基本遍历

cs 复制代码
SortedSet<string> fruits = new SortedSet<string> { "Banana", "Apple", "Cherry" };
  • foreach 遍历(按排序顺序)
    *

    cs 复制代码
    // foreach 遍历(按排序顺序)
    foreach (string fruit in fruits)
    {
        Console.WriteLine(fruit); // Apple, Banana, Cherry
    }
  • 使用枚举器
    *

    cs 复制代码
    // 使用枚举器
    using (var enumerator = fruits.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            Console.WriteLine(enumerator.Current);
        }
    }

反向遍历

cs 复制代码
SortedSet<int> numbers = new SortedSet<int> { 1, 3, 5, 7, 9 };

// 反向遍历
foreach (int number in numbers.Reverse())
{
    Console.WriteLine(number); // 9, 7, 5, 3, 1
}

SortedSet 的优点和适用场景

优点

  • 自动保持元素排序,无需手动干预。
  • 确保元素唯一性,避免重复。
  • 高效的操作性能(O(log n))。
  • 支持集合操作和子集视图。

适用场景

  • 需要有序且不重复的元素集合,例如排行榜、时间线。
  • 实现优先级队列(尽管 C# 有 PriorityQueue<T>)。
  • 执行集合操作,如并集、交集等。

SortedSet 与其他集合类型的区别

  • 与 HashSet<T> 的区别
    • HashSet<T> 不保持顺序,查找时间为 O(1)。
    • SortedSet<T> 保持顺序,查找时间为 O(log n)。
  • 与 List<T> 的区别
    • List<T> 允许重复元素,不自动排序。
    • SortedSet<T> 不允许重复,自动排序。
  • 与 SortedList<TKey, TValue> 的区别
    • SortedList<TKey, TValue> 是键值对集合,键排序。
    • SortedSet<T> 是元素集合,元素本身排序。
相关推荐
CoderIsArt9 小时前
自动加工脚本程序变量管理器
c#
unicrom_深圳市由你创科技15 小时前
C#与 Prism 框架:构建模块化的 WPF 应用程序
开发语言·c#·wpf
钢铁男儿15 小时前
C#核心概念解析:析构函数、readonly与this关键字
开发语言·javascript·c#
拜特流动17 小时前
C# Socket对象创建方式详解
网络·c#
JuneXcy17 小时前
班级管理系统
c#
Kookoos18 小时前
ABP VNext + CRDT 打造实时协同编辑
c#·.net·yjs·crdt·abp vnext
o0向阳而生0o20 小时前
54、C# 委托 (Delegate)
开发语言·c#·.net
军训猫猫头20 小时前
95.WPF中图片控件的使用与资源路径设置 WPF例子 C#例子
ui·c#·.net·wpf
qq_3404740220 小时前
5 WPF中的Page页面的使用
开发语言·c#·wpf
码观天工21 小时前
.NET AI 生态关键拼图:全面解读 AI Extensions 和 Vector Extensions 如何重塑.NET开发生态
ai·c#·.net·向量数据库