zoukankan      html  css  js  c++  java
  • 《C#从现象到本质》读书笔记(九)第11章C#的数据结构

    《C#从现象到本质》读书笔记(九)第11章C#的数据结构

    C#中的数据结构可以分为两类:非泛型数据结构和泛型数据结构。

    通常迭代器接口需要实现的方法有:1)hasNext,是否还有下一个元素。2)Next,移动到下一个元素。3)Reset,重置。

    C#中对迭代器模式的实现就是IEnumerable接口。

    使用yield关键字实现方法GetEnumerator。yield的延迟执行特性体现在:只有当需要取值时,才会执行,否则状态机的状态就停在0。

    foreach迭代时,不能直接更改集合成员的值,但可以对成员本身的字段和属性进行重新赋值。

    IEnumerable的缺点如下:1)IEnumerable功能有限,不能插入和删除。2)访问IEnumerable只能通过迭代,不能使用索引器。迭代时非线程安全的。3)访问IEnumerable必定造成一次求值。

    IEnumerable小结如下:

    1)IEnumerable及其泛型版本是所有集合的基础,它赋予集合迭代的能力。

    2)通常将迭代中拿出来的元素称为iterator。

    3)实现IEnumerable接口,必须实现它唯一的方法GetEnumerator。

    4)方法GetEnumerator返回一个IEnumerator类型的输出。

    5)IEnumerator接口拥有一个Current属性,我们需要实现它的get方法,返回当前的iterator。

    6)需要为IEnumerator类型增加一个int类型的值,记录当位置。该类型的初始值为-1。IEnumerator类型的Reset方法将这个值设为-1。

    7)IEnumerator接口的MoveNext方法将位置增加1,并返回是否还有下一个元素。

    8)通过yield简化方法GetEnumerator的实现。

    9)在C#中使用foreach将会隐式地调用MoveNext方法。

    10)IEnumerable<T>是整个LINQ的基础。整个LINQ都基于IEnumerable<T>的扩展方法。C#大部分数据结构都实现了IEnumerable<T>。

    11)IEnumerable的派生类由于没有反省,所以基本不考虑使用。

    常用数据结构特征以及操作时间复杂度见下表

    数据结构 类型及备注 插入和删除 查找
    Array

    顺序存储的线性表

    定长

    不支持(这里的插入与删除指会更改表长的行为) O(N)
    LinkedList<T>

    链式储存的线性表

    不定长

    无法用下表访问

    O(1) O(N)
    List<T>

    顺序储存的线性表

    不定长

    动态扩容

    O(N),结尾则是O(1) O(N)
    Stack<T>

    不定长

    动态扩容

    O(1) 只能访问栈顶
    Queue<T>

    队列

    不定长

    动态扩容

    O(1) 只能访问队头
    Dictionary<K,T>

    保存键值对

    使用开散列法

    不定长

    动态扩容

    长度总为质数

    O(1) O(1)
    SortedList<K,T>

    保存键值对

    内部使用数组实现

    保持有序

    不定长

    O(log N) O(log N)
    SortedDictionary<K,T>

    保存键值对

    内部使用红黑树实现

    保持有序

    不定长

    O(log N) O(log N)
    HashSet<T>

    使用开散列法

    不定长

    动态扩容

    长度总为质数

    是不含值的字典,故复杂度和它完全相同

    O(1) O(1)
    SortedSet<T>

    内部使用红黑树实现

    保持有序

    不定长

    是不含值的SortedDictionary<K,T>,故复杂度和它完全相同

    O(log N) O(log N)

    如何选择数据结构:

    首先对于栈和队列,直接使用对应的数据结构即可。对于普通数据源:

    如果数据源不是键值对:

    a)数据量大,没有重复数据:使用HashSet<T>。

    b)数据量大,但可能有重复数据;或数据量小:使用Array,List<T>或LinkedList<T>。

    c)没有重复数据,且希望集合处于有序状态:使用SortedSet<T>。

    d)有重复数据,且希望集合处于有序状态:没有现车的数据结构提供,可以考虑基于数组实现一个。

    如果是键值对:首选是类型安全的字典,然后,如果希望集合处于有序状态,从SortedList<k,T>和SortedDictionary<K,T>中进行权衡。如果数据源数据很少,可以考虑List<KeyValuePair<K,T>>替代字典。

     哈希(散列)表(Hashtable)是一种键值对类型的数据结构。它的特点是查找速度飞快。C#的HashTable类把a的最大值定为0.72(Java为0.75),当HashTable中的被占用空间达到72%的时候就将该HashTable自动扩容。

    冲突解决技术可分为两大类:开散列法(又称为链地址法)和闭散列法(又称为开放地址法)。对于开散列法,发生冲突的元素存储于数组空间之外。Dictionary<K,T>使用的就是这种方式。对于闭散列法,发生冲突的元素存储于数组空间之内。HashTable使用的就是这种方式。

    C#的HashTable内部借助了数组,并采用开放寻址加双重哈希。它通过一个结构体bucket来表示哈希表中的单个元素,这个结构体中有三个成员:a)key:表示键,即哈希表中的关键字。b)表示值,即跟关键字所对应的值。c)hash_coll:int类型,用于表示键所对应的哈希码。

    ArrrayList是实现了基于动态数组的数据结构,存在不安全类型与装箱拆箱的缺点。

  • 相关阅读:
    数据库复习之数据库系统概论
    C++前缀表达式和后缀表达式
    MySQL——排序和分页
    MySQL——联表查询
    MySQL——Where条件子句
    MySQL——DQL查询数据(Select)
    MySQL——外键、DML语言(添加、修改、删除)
    MySQL——数据库的操作、属性
    MySQL——简介和安装
    MySQL——数据库
  • 原文地址:https://www.cnblogs.com/Lvkang/p/9728247.html
Copyright © 2011-2022 走看看