有序集
具体到一种结构时,如果仍然称为集,那么这种结构一般是不允许有重复值的。
集在数学里具有这样的定义。我们一般称数据集合的时候,只是叫顺口了,没有严格按照数学定义说。
有序集基于二分查找,相较于普通的无序集速度更快(更数组和列表这种直接用索引的还是没得比)。
但是在添加和删除元素的时候,有更大的成本。
另外他的排序只在添加元素时进行一次,对已经加进来的数据再做更改,可能导致严重问题。
class Student : IComparable<Student>
{
public int id;
public int age;
public string name;
public int CompareTo(Student? other) => id.CompareTo(other.id);
}
SortedSet<Student> sortedSet = new SortedSet<Student>();
有序集只能储存实现了排序接口(IComparable泛型版本)的类型。否则需要为其指定比较器。
比较器是一个实现了比较器接口(IComparer泛型版本)的实例,也就是说你需要新建一个类。
添加元素
sortedSet.Add(new Student() {id=12,age=18,name="小明" });
sortedSet.Add(new Student() {id=12,age=16,name="小红" });
Add方法可以将元素添加到有序集中。集不能有并列值。
如果添加的元素在顺序上和现有元素具有并列关系,那么会添加失败。
不过这不会报错,Add方法会返回一个bool值,指示这次添加是否成功。
添加序列
UnionWith方法的字面是获得自己和他的并集。
实际效果是把目标序列整个尝试添加到自己身上。
Student[] stuArr = { new Student() { id = 11, age = 12, name = "小绿" }, new Student() { id = 3, age = 18, name = "小蓝" } };
sortedSet.UnionWith(stuArr);
删除元素
删除元素不需要完全提供元素本身。只需要提供对排序有用的部分就行了。
他会查找和参数在排序上有并列关系的元素,即便这个元素和参数不是同一个东西。
Console.WriteLine(sortedSet.Count);
sortedSet.Remove(new Student() { id=12});
Console.WriteLine(sortedSet.Count);
确定是否包含元素
和删除元素一样,他不会检查参数和他储存的元素是不是真的是同一个。
只检查参数和自己元素中有没有并列关系的。
Console.WriteLine(sortedSet.Contains(new Student() { id = 12 }));
尝试获取元素
sortedSet.TryGetValue(new Student() { id = 11 }, out Student st);
Console.WriteLine(st.name);
同上,如果你知道他如何排序,只需要提供与排序有关的信息。
输出参数的值,是他里面的元素,包含着剩下部分的信息。
这个方法本身还会返回一个bool值,指示是否真的找到了有并列关系的元素。如果没找到,输出参数是默认值。
获得最值
有序集提供Min和Max两个属性,允许你获取当前的最小值和最大值。
但有序集不是时刻监视内部元素并排序的,如果你修改了他们的状态,可能导致整个排序都出现问题。
Console.WriteLine(sortedSet.Min.id);
sortedSet.Min.id = 999;
Console.WriteLine(sortedSet.Min.id);
有序列表
有序列表虽然说着列表,但是却和列表没什么关系。他更像字典,使用Key,Value对。
有序列表使用Key进行排序。每次添加或移除元素的时候都会对整个Key集合重新排序。
Value集合会跟随Key集合做参照排序。
Key类型必须是可排序的(实现IComparable泛型接口)
SortedList<string, int> sortedList = new SortedList<string, int>();
添加元素
sortedList.Add("null", 12);
sortedList["hello"] = 8;
添加元素的操作和字典的操作一样,但是没有了TryAdd方法。
访问元素
和有序集一样,寻找Key值只检查有没有并列关系,不在乎是不是相同的。
Console.WriteLine(sortedList["hello"]);
删除指定Key与配对的Value
使用Remove方法,会移除和参数位置并列的Key,与其所对应的Value。
使用索引删除Key和Value
因为有序列表使用数组储存Key和Value,所以还是能找出他们的索引。
在找到索引之后,可以使用RemoveAt删除指定索引下的数据。
int index = sortedList.IndexOfKey("null");
sortedList.RemoveAt(index);
找索引这项工作也使用查找顺序并列完成。
有序字典
有序字典和有序列表几乎一样。
除了有序字典使用二叉搜索树而不是数组。
因此有序字典在插入和删除上比需要整理顺序的有序列表更快。
但是有序字典消耗更多的内存。
SortedDictionary<string, int> sortedDictionary = new SortedDictionary<string, int>();