美文网首页
c#常用数据结构解释

c#常用数据结构解释

作者: 王清水 | 来源:发表于2019-08-15 16:15 被阅读0次

    一,数组 Array

    特点:

    数组存储在连续的内存上;数组的内容类型都相同;数组可以通过下面进行直接访问;

    创建过程:

    创建一个新的数组时将在CLR托管堆中分配一块连续的内存空间来存放数量为size,类型为所声明类型的数组元素,如果类型为值类型,则将会有size个未装箱的该类型的值被创建,如果是引用类型,将会有size个相应类型的引用被创建;

    携带方法: 略

    优劣:

    由于内存连续,所以索引速度非常快,访问一个元素的速度与元素的数量无关,且赋值和修改都非常简单;

    同样,由于内存连续且声明的时的长度是固定的,在插入新元素和长度初始声明时会存在风险;

    拓展1:装箱和拆箱

    基础知识:

    值类型在栈中分配内存,在声明初始化才能使用,且不能为null;值类型超出作用范围系统自动释放内存;主要由结构(整型,浮点型,decimal,bool,用户自定义struct结构)和 枚举(enum)组成;

    引用类型在堆中分配内存,初始化时默认为null;引用类型是通过垃圾回收机制进行回收;包括类,接口,委托,数组以及内置的引用类型object和string;

    事件原因:

    由于c#中所有的数据类型都是由基类System.Object继承而来,所以,值类型和引用类型的值是可以通过显式或隐式操作来相互转换,而这个过程就是装箱(boxing)和拆箱(unboxing)过程;

    装箱:

    装箱是  值类型  到object类型    到此值类型所实现的任何接口的隐式转换(转为接口依旧要装箱);对值类型装箱会在堆中分配一个对象实例,并将该值复制到新的对象中;

    拆箱:

    拆箱是  object类型到值类型  或  从接口类型到实现该接口的值类型的显示转换;

    取消拆箱:

    检查对象实例,确保它是给定值类型的一个装箱值(拆箱后没有转成原类型,编译时不会出错,但是运行会出错;用GetType.ToString()判断时一定要使用类型全称,如System.String 替换掉 String);

    将该值从实例赋值到值类型变量中;

    频繁的装箱和拆箱对性能的影响很大;故手动的操作很重要

    二,ArrayList

    特点:

    消除了数组创建时必须指定长度所带来的风险;它属于System.Collections命名空间下的一部分;

    可以存储不同类型的元素(元素会都会统一当成Object来处理  => 加入不同类型元素是被允许的);

    创建过程:

    ArrayList arryListname = new ArrayList();

    携带方法:略

    优劣:

    由于ArrayList把不同的类型都当成Objec来处理

    =>所以很可能在使用时发生类型不匹配问题,所以,ArrayList不是类型安全的;

    =>会不断的装箱;时间损耗同时也会效率降低

    三,List<T> 泛型List

    特点:

    长度可以灵活改变;

    内部实际是Array来实现的;

    创建过程:

    List <string> stringList = new List<string>();

    携带方法:略

    优劣:

    保证了类型安全; 取消了装箱和拆箱的操作;融合了ArrayList的长度自由变化;

    四,LinkedList<T> 链表

    特点:

    链表在内存存储傻的排序上可能是不连续的;

    链表是通过上一个元素指向下一个元素来排序,不能通过下标来访问;

    不用动态扩充长度;

    创建过程:

    LinkedList<string> myLinkedList = new LinkedList<string>();

    携带方法: 略

    优劣:

    由于内存存储的不一定连续性,访问无法通过下标,必须从开始节点开始遍历,逐次遍历下一个节点直到找到目标,所以查找方面无法与Array相比;

    由于没有连续内存存储,所以在增减节点(插入删除)操作上很便利;

    链表适合元素数量不稳定且经常操作两端来增减节点的情况;

    五,Queue<T> 队列

    特点:

    一种先入先被删除(first in first out)的线性表;

    默认情况下,初始容量为32;增长因子为 2.0, 使用TrimExcess来降低容量;

    加入元素时,将通过又一次分配内部数组来依据须要自己主动增大容量;

    能接受null作为有效值,并且允许重复的元素;

    创建过程:

    Queue<int> q = new Queue<int>();

    携带方法:

    q.Enqueue(1); q.Enqueue(2); q.Enqueue(3); q.Enqueue(4);     //依次放入1,2,3,4

    q.Count();     //返回队列中元素的数量

    q.Dequeue();      //取出排在第一的元素, 队列中只剩下2,3,4

    q.Peek();     //查看队列中的第一元素, 只是查看,没有取出, 队列中还有2,3,4

    foreach(int y in q) { cw{y}};    //遍历查看队列中的元素

    q.TrimExcess();重置队列容量(将容量设置为队列中元素的实际数目)

    ....

    注意:

    若要区分空值和 Queue 结尾,请检查 Count 属性或捕捉 Queue 为空时引发的 InvalidOperationException异常;

    六,Stack<T>

    特点:

    一种先入后出(first in last out)的线性表;默认情况下;

    增长因子为 2.0, 使用TrimExcess来降低容量;

    加入元素时,将通过又一次分配内部数组来依据须要自己主动增大容量;

    能接受null作为有效值,并且允许重复的元素;

    创建过程:

    Stack<T> s = new Stack<T>():

    携带方法:

    Puch();     //添加一个值到集合顶部

    Pop();    //删除一个顶部一个值

    Peek();      //查看顶部值

    ...

    七,Dictionary<K,T>

    特点:

    元素为键值对,键必须唯一,键值都可以是任何类型;通过键读取一个值的时间复杂度为O(1);

    内部维持的是两个数组;

    创建过程:

    Dictionary<K, T> D = new Dictionary<K, T>();

    携带方法:

    Add(“a”,“aa”);     //添加字符串结构

    D["a"];     //取值,得到aa

    D["a"] = ''bb";      //修改key为a的值为“bb”

    D.Remove("a");    //删除元素

    D.ContainsKey("a");      //判断key是否存在

    foreach (string key in D.Keys){ Console.WriteLine("Key = {0}", key);}    //遍历key

    foreach (string key in D.Values){ Console.WriteLine("Key = {0}", key);}    //遍历value

    foreach (KeyValuePair<string, string> kvp in D){Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);}      //遍历字典

    ...

    注意:

    空间换时间的字典,啥都能刚!

    结论:

    Array 需要处理的元素数量确定并且需要使用下标时可以考虑,不过建议使用List<T>

    ArrayList 不推荐使用,建议用List<T>

    List<T>泛型List 需要处理的元素数量不确定时 通常建议使用

    LinkedList<T> 链表适合元素数量不固定,需要经常增减节点的情况,2端都可以增减

    Queue<T> 先进先出的情况

    Stack<T> 后进先出的情况

    Dictionary<K,T> 需要键值对,快速操作

    相关文章

      网友评论

          本文标题:c#常用数据结构解释

          本文链接:https://www.haomeiwen.com/subject/zspbjctx.html