数据结构也是很重要的知识点,了解他们的特性可以使得在编写代码的时候选择合适的数据结构,避免在之后维护和增加需求的时候的麻烦,提高效率。
Array数组:
- 数组储存在连续的内存上。
- 数组的元素都是相同类型或者类型的衍生类型。
- 数组可以直接通过下标访问。比如需要访问数组的第i个元素,则可以使用array[i]来访问。
数组的特点是索引速度非常快,因为他是储存在连续的内存上的,因此访问一个元素的时间是恒定的。但是也正因为他是连续储存的,要进行插入新的元素时就会非常不方便,且在声明一个薪数组时,必须声明长度或初始化元素,这就会存在一个潜在的问题——当声明的长度过长时,显然会浪费内存,当声明长度过短时,则面临溢出的风险。
ArrayList数组:
为了解决Array创建时必须指定长度,以及只能存放相同类型的缺点时,就可以使用ArrayList,它有如下特性:
- 无需声明长度,它是按照其中存储的数据来动态增长和缩减的。(动态数组的概念,这边也有深入的知识点,之后总结)
- ArrayList可以储存不同类型的元素。这是由于ArrayList会把它的元素都当做Object来处理,因此加入不同类型的元素是允许的。(但是涉及到拆装箱的问题,上一篇笔记讲过了,此处不再赘述)
List<T>数组:
为了解决ArrayList不安全类型与拆装箱的问题,在C#引入了泛型的概念后,List<T>作为一种新的数据类型引入。并且List<T>是工作中常用到的数据类型,创建时无需指定长度大小,添加元素时也无需担心列表大小调整问题,与ArrayList最大的不同就是创建时需要声明变量类型,这点与Array相似,只能存储统一类型,但保证了安全与减少了GC的产生。
- 保证了类型安全。
- 取消了拆装箱的操作,以及由于引入泛型而无需运行时类型检查。因此List<T>是高性能的。
- 融合了Array可以快速访问的优点,以及ArrayList长度可以灵活变化的优点。
链表LinkedList<T>:
所谓链表就是每一个元素都指向下一个元素,形成一个链。创建一个链表时,仅需持有第一个结点,即头结点head,下一个结点用.Next表示。
在链表中,查找元素的线性运行时间为O(n),需要从头结点逐个查找。删除操作的话,查找到目标节点n后,只需要将前一个n-1结点的Next指向n+1即可,插入也是同理。
与数组不同的是,链表中的内容顺序是按照各个对象的指针来决定的,因此它的排序不一定是连续的,因此不能直接用下标访问。
因此链表的优点是特别适合以排序的顺序动态地添加新元素,如果用数组的话不仅要移动其余所有元素,甚至要考虑重新调整容量。
队列Queue<T>:
队列是一种只能在表前端进行删除,在表的后端进行插入操作的一种线性表,即先进先出顺序。
可以想象成一根管道,先进去的数据先出来,后进入的数据需要等待排队到他为头时,才能出。
栈Stack<T>:
栈和队列不同,他是先进后出顺序,只允许在表的一端进行插入和删除运算,这一段被称为栈顶,另一端为栈底。
可以想象为一个桶,先放入的数据被后放入的数据压住,只能让最上面的数据被删除后,才能轮到下面一层的数据。