文章目录
-
-
- 自定义集合
-
- 什么是迭代器
- 迭代器 Enumerator
- 集合 IEumerable
- yield return和yield break
- 常用集合
-
- 字典Dictionary
- 栈Stack、队列Queue在数据结构和算法中常用
- 双向列表LinkedList、IComparable、IList、[]索引运算符
-
自定义集合
什么是迭代器
- 首先通过场景实现。
class MyList{
private int[] Nums { get; set; }
public MyList(int n){
Nums = new int[n];
var r = new Random();
foreach(var i in Nums){
Num[i] = r.Next(1,10);
// 上句会报错,因为foreach是只读,无法赋值。
}
// 因此不用foreach(),用for如下
for(int i=0; i<n; i++){
Num[i] = r.Next(1,10);
}
}
private int Index = -1;
public bool MoveNext(){
Index++;
return Index < Nums.Length;
}
public int Current {get {return Nums[Index];}}
}
class Program{
...Main(..){
var list = new MyList(5);
while(list.MoveNext()){
Console.WriteLine(list.Current);
}
// 这里改为迭代器更为方便
}
}
- 上述程序中,如果想重新打印两次list,则需要在Main()中嵌套两层while(){}。
- 但是两个while共用一个list,list中的Index只用于维护一层循环。因此引入迭代器。
迭代器 Enumerator
- 把上例中list中用于迭代的部分拉出来单独做一个迭代器,再增加一个方法调用迭代器。
class Enumerator{
private int[] Nums = null;
public Enumerator(int[] nums){
Nums = nums;
}
private int Index = -1;
public bool MoveNext(){
Index++;
return Index < Nums.Length;
}
public int Current {get {return Nums[Index];}}
}
- 在MyList中增加方法调用迭代器。
- 有了迭代器,在Main()中使用如下。
class MyList{
private int[] Nums { get; set; }
public MyList(int n){
Nums = new int[n];
var r = new Random();
for(int i=0; i<n; i++){
Num[i] = r.Next(1,10);
}
}
public Enumerator GetEnumerator(){
return new Enumerator(Nums);
}
}
class Program{
...Main(..){
var list = new MyList(5);
var e1 = list.GetEumerator();
while(e1.MoveNext()){
Console.WriteLine(e1.Current);
var e2 = list.GetEumerator();
while(e1.MoveNext()){
Console.WriteLine("\t" + e2.Current);
}
}
}
}
- 其实上述也是设计模式中的迭代器模式。
集合 IEumerable
- 类实现迭代器功能,C#中可称为集合。
- 所以集合是实现了IEnumerable接口的类。
class MyList : IEnumerable<int>{
// 接口自带方法,是因为以前没有泛型而留下的问题
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator(){
throw new NotImplementedException();
}
}
yield return和yield break
- yield按照我的理解是输出迭代器中第几个值,以及用break停止。
class MyList : IEnumerable<int>{
private int[] Nums { get; set; }
public MyList(int n){
Nums = new int[n];
var r = new Random();
for(int i=0; i<n; i++){
Num[i] = r.Next(1,10);
}
}
public IEnumerable<int> GetEnumerator(){
yield return 1;
yield return 2;
yield return 3;
// 调用该方法后根据循环依此输出1,2,3。
// yield break 一般和if(){}联用。
// 比较常用的是循环与yield return联用。
foreach(var i in Nums){
yield return i;
}
}
}
class Program{
...Main(..){
var list = new MyList(5);
var e1 = list.GetEumerator();
foreach(var i in list){
Console.WriteLine(e1.Current);
foreach(var i2 in list){
Console.WriteLine("\t" + e2.Current);
}
}
}
}
- 迭代器在我看来就是不一口气输出,二是可以与Main()中循环一步步慢慢来。
- 迭代器和foreach关系:能用foreach()一定有迭代器。
- foreach不可以修改,只读。
常用集合
- List
-
Dictionary<TKey, TValue>
字典的遍历,其中涉及到哈希表存储数据,查找速度很快。
- SortedList、SortDic…
- Stack<T>
- Queue<T>
- LinkedList<T>
字典Dictionary
class Program{
...Main(..){
var dic = new Dictionary<int, string>();
dic.Add(1, "a");
dic.Add(2, "b");
dic[1] = "aa";
var dic1 = new Dictionary<int, Dictionary<int, string>>();
}
}
}
}
栈Stack、队列Queue在数据结构和算法中常用
- 比较经典的如字符串表达式求值等。
- “(1+2)*3”,用两个栈,一个栈存操作符,一个栈存数字。
双向列表LinkedList、IComparable、IList、[]索引运算符
- IComparable中有CompareTo()方法。