虚拟主机多个网站,登录免费注册网址,请问电商是做什么的,本地58同城招聘网找工作目录 数组使用场景 ArrayList数组ArrayList的缺点 List\T\数组List\T\有以下3点好处 链表链表与数组的不同之处链表的优势数组和链表的应用场景 LinkedList\T\C#中内置的双向链表LinkedList使用场景 队列#xff08;Queue\T\#xff09;和栈… 目录 数组使用场景 ArrayList数组ArrayList的缺点 List\T\数组List\T\有以下3点好处 链表链表与数组的不同之处链表的优势数组和链表的应用场景 LinkedList\T\C#中内置的双向链表LinkedList使用场景 队列Queue\T\和栈Stack\T\queue队列内部实现 栈内部实现 Hashtable哈希表如何处理哈希冲突避免哈希冲突解决哈希冲突开放寻址法的简单实现——线性探查Linear Probing针对线性探查方式所存在的问题一种改进的方式为二次探查Quadratic Probing 二度哈希二度哈希的工作原理loadFactorHashtable类的实例中添加新元素时需要检查以保证元素与空间大小的比例不会超过最大比例。如果超过了Hashtable类实例的空间将被扩充。空间扩充的步骤如下 Dictionary\K,T\字典冲突解决机制DictionaryK,T类的缺点使用场景 数组
使用场景
元素的数量是固定的并且需要使用下标时。
ArrayList数组
为了解决Array创建时必须指定长度以及只能存放相同类型的缺点而推出的数据结构。
ArrayList的缺点
ArrayList是类型不安全的。因为把不同的类型都当作Object来做处理很有可能会在使用ArrayList时发生类型不匹配的情况。数组存储值类型时并未发生装箱但是ArrayList由于把所有类型都当作了Object所以不可避免的是当插入值类型时会发生装箱操作在索引取值时会发生拆箱操作。因此在频繁读写 ArrayList 时会产生额外的开销导致性能下降。
ListT数组
可以认为ListT 类是 ArrayList 类的泛型等效类。
ListT有以下3点好处
即确保了类型安全。因此ListT是类型安全的。取消了装箱和拆箱的操作以及由于引入泛型而无需运行时类型检查。因此ListT是高性能的。融合了Array可以快速访问的优点以及ArrayList长度可以灵活变化的优点。
链表
链表与数组的不同之处
数组中的内容在内存中是连续排列的可以通过下标来访问。 链表中内容的顺序则是由各个对象的指针所决定的这就决定了其内容的排列不一定是连续的所以不能通过下标来访问。
链表的优势
使用链表最主要的优势就在于向链表中插入或删除节点时无需考虑调整结构的容量。相反的对于数组来说容量始终是固定的且数组中的内容在内存中是连续的。因此如果需要存放更多的数据则面临着需要调整数组容量的现实这就会引发新建数组、数据拷贝等一系列复杂且影响效率的操作。即使是ListT类虽然其对开发人员隐藏了容量调整的复杂性但实质上性能的损耗是必须考虑的。
数组和链表的应用场景
数组适合数据的数量是有上限且需要快速访问其元素内容的情况. 链表适合元素数量不固定且需要经常增删结点的情况。
LinkedListT
C#中内置的双向链表LinkedList
在Unity 3D开发过程中由于C#已经为开发者封装了一个对应链表的类——LinkedListT类。因此可以很方便地通过LinkedListT来实现链表的功能。而和LinkedListT类相配套的C#还提供了链表的结点类——LinkedListNodeT类以用来代表链表中的结点LinkedListT对象中的每个节点都属于LinkedListNodeT类型。由于LinkedListT是双向链表因此每个节点向前指向Next节点向后指向Previous节点。 需要说明的一点是LinkedListT类的插入和移除的运算复杂度都是O(1)。而由于该列表还维护内部计数因此获取Count属性的运算复杂度也为 O(1)。
如何创建一个链表LinkedListT以及最常见的几种操作。
AddFirst将一个新结点加入该链表的第一个结点的位置RemoveFirst将第一个结点移除AddLast将一个新节点加入该链表最后一个结点的位置以及在某个结点前后插入新的结点的AddBefore和AddAfter方法。对链表中的结点类LinkedListNode的各种操作。
使用场景
元素需要能够在列表的两端添加时。否则使用ListT。
队列QueueT和栈StackT
queue队列
内部实现
在QueueT内部有一个存放类型为T的对象的环形数组并通过head 和tail变量来指向该数组的头和尾。当使用Enqueue方法将新的元素入列时会判断队列的长度是否足够。若不足则依据增长因子来增加容量例如当为初始的2.0时则队列容量增长2倍。 在默认情况下QueueT的初始化容量是32但是也可以通过构造函数指定容量。 元素的进出顺序是先进先出FIFO
栈
栈Stack又名堆栈它和队列一样是一种运算受限的线性表。 其限制是仅允许在表的一端进行插入和删除的操作运算。这一端称为栈顶相对的把另一端称为栈底。 向一个栈插入新元素称为进栈、入栈或压栈。 一个栈删除元素称为出栈或退栈它是把栈顶元素删除使其相邻的元素成为新的栈顶元素。 元素的进出顺序是后进先出LIFO
内部实现
内部同样使用了数组来实现。内部结构可以通过一个垂直的数组来形象的表示。
Hashtable哈希表
哈希表Hash Table也叫散列表是根据关键码/值Key/value而直接进行访问的数据结构。也就是说它通过把关键码/值映射到表中一个位置来访问记录以加快查找的速度。这个映射函数叫哈希函数或散列函数存放记录的数组就叫哈希表。
如何处理哈希冲突
处理哈希冲突时也有两种思路——避免和解决
冲突避免机制Collision Avoidance冲突解决机制Collision Resolution
避免哈希冲突
避免哈希冲突的一个方法就是尽可能先择合适的哈希函数。
解决哈希冲突
将要插入的元素放到另一块空间中因为相同的哈希位置已经被占用了。开放寻址法Open Addressing
开放寻址法的简单实现——线性探查Linear Probing
当插入新的元素时使用哈希函数在哈希表中定位元素位置。检查哈希表中该位置是否已经存在元素。如果该位置内容为空则插入并返回否则进行步骤3的操作。如果该位置为i则检查i1是否为空。如果已被占用则检查i2。依此类推直到找到一个内容为空的位置。 线性探查Linear Probing方式虽然简单但并不是解决冲突的最好策略因为它会导致同类哈希的聚集Primary Clustering。这会导致搜索哈希表时冲突依然存在。 针对线性探查方式所存在的问题一种改进的方式为二次探查Quadratic Probing
即每次检查位置空间的步长为平方倍数。也就是说如果位置s被占用则首先检查s12处然后检查s-12、s22、s-22、s32…以此类推而不是像线性探查那样以s1、s2…方式增长。 尽管如此二次探查同样也会导致同类哈希聚集问题Secondary Clustering。 二度哈希
当在哈希表中添加或获取一个元素时会发生哈希冲突。前面简单地介绍了两种冲突解决策略即线性探查Linear Probing和二次探查Quadratic Probing。 二度哈希使用了Θ(m2)种探查序列而线性探查Linear Probing和二次探查QuadraticProbing使用了Θ(m)种探查序列因此二度哈希提供了更好的避免冲突的策略。
二度哈希的工作原理
有一个包含一组哈希函数H1…Hn的集合。当需要从哈希表中添加或获取元素时首先使用哈希函数H1。如果导致冲突则尝试使用H2。以此类推直到Hn。所有的哈希函数都与H1十分相似不同的是它们选用的乘法因子multiplicative factor。 当使用二度哈希时重要的是在执行了hashsize次探查后哈希表中的每一个位置都有且只有一次被访问到。也就是说对于给定的key对哈希表中的同一位置不会同时使用H1和H2 。在Hashtable类中使用二度哈希公式其始终保持(1 ((GetHash(key) 5) 1) %(hashsize - 1)与hashsize互为素数 (两数互为素数表示两者没有共同的质因子)
loadFactor
Hashtable类中还包含了一个私有成员变量loadFactorloadFactor指定了哈希表中元素数量与位置slot数量之间的最大比例。 例如如果loadFactor 等于0.5则说明哈希表中只有一半的空间存放了元素值其余一半都为空。 哈希表的构造函数允许用户指定loadFactor值定义范围为0.1至1.0。然而不管提供的值是多少范围都不会超过72%。即使传递的值为1.0Hashtable类的loadFactor值还是0.72。微软官方认为loadFactor的最佳值为0.72这平衡了速度与空间。因此虽然默认的loadFactor为1.0但系统内部却自动地将其改变为0.72。所以建议使用缺省值1.0但实际上是 0.72。
Hashtable类的实例中添加新元素时需要检查以保证元素与空间大小的比例不会超过最大比例。如果超过了Hashtable类实例的空间将被扩充。空间扩充的步骤如下
Hashtable类实例的位置空间几乎被翻倍。准确地说位置空间值从当前的素数值增加到下一个最大的素数值。因为二度哈希时Hashtable类实例中的所有元素值将依赖于Hashtable类实例的位置空间值所以Hashtable类实例中保存的所有值也需要重新二度哈希。
DictionaryK,T字典
DictionaryK,T使用强类型来限制Key和Item当创建DictionaryK,T实例时必须指定Key和Item的类型。
冲突解决机制
DictionaryK,T还采用了不同的冲突解决策略Collision Resolution Strategy这种技术称为链接技术Chaining。 链接技术Chaining将采用额外的数据结构来处理冲突。DictionaryK,T中的每个位置slot都映射到了一个链表。当冲突发生时冲突的元素将被添加到桶bucket列表中。
DictionaryK,T类的缺点
它的缺点就是空间。以空间换时间通过更多的内存开销来满足对速度的追求。在创建字典时可以传入一个容量值但实际使用的容量并非该值。而是使用不小于该值的最小质数作为它使用的实际容量容量的最小值是 3。当有了实际容量后并非直接实现索引而是通过创建额外的两个数组来实现间接索引即int[] buckets和Entry[] entries两个数组。因此面临的情况就是即便新建了一个空的字典那么伴随而来的是两个长度为3的数组。所以当处理的数据不多时还是慎重使用字典为好在很多情况下使用数组也是可以的。
使用场景
需要使用键值对KeyValue来快速添加和查找并且元素没有特定的顺序时。