c#中的数据结构

主要介绍Array(数组)、ArrayList、List<T>、LinkedList<T>、Stack、Queue、HashTable、Dictionary<K,T>

1. Array(数组)

a. 数组不是“数字”组,而是“数据”组,任何类型的类或者结构体都可以是里面的一个元素。

b. 数组是定长的,如果要扩容则需要从新定义一个数组,让后复制过去。

c. C#中二维数组的声明,和java,c++不一样,是以这种形式的:int[,] a=new int[2,5];只有一个中括号。

d. 数组在内存中的存储是连续的,查询一个元素为O(1),但是要在中间删除或者添加一个元素,则为O(n)。所以它适合在经常查询的时候使用。

2. ArrayList

为了改进数组定长的缺点,引入了ArrayList

a. 它的长度不固定,可以添加任意多个。

b. 它的每个元素可以是不同的,因为它后面没有加<T>,其实是任何元素都是会被转换为Object(终极基类)添加进去。(好像只有这个数据结构的元素类型可以是不同的)

c. 因为它添加每个元素都存在装箱操作,非常消耗性能,所以不推荐使用。

d. 因为每个元素不同,在拆箱的时候可能不安全。

3. List<T>(推荐使用)

为了改进ArrayList需要频繁装箱的不足,引入了List<T>

a. 因为有<T>,在声明时需要指定是什么类型,添加进去的必须是同一种类型,或者是该类型的子类。

b. 但其实内部也是由数组实现的,只是向开发者隐藏了数组的新建与复制。

4. LinkedList<T>

就是数据结构里面学习的双向链表,其实很多函数系统已经帮我们实现了,我们不用像在数据结构课上那样要自己实现。

a. 和数组很大的不同是存储不是连续的,而是由元素中的前项与后项指针指引到相邻的元素。当然一个元素除了存储本身的值,还要存储两个指针。

b. 查询一个元素为O(n),但是删除和添加是O(1),适合不常查询,而频繁增删的。

c. 链表会维护一个总数的值Count,所以获得总数的复杂福也是O(1)

5. Stack(栈)

a. 最主要的特性就是后进先出(LIFO),最后添加进去的元素必定是第一个被取出来的。

b. 元素也是相同的,不然入栈出栈不好操作啊

c. 入栈出栈函数(push和pop)也是api帮你写好了的

6. Queue(队列)

a.  先进后出(FIFO)

b. 存储结构其实是一个环,就是最后一个元素里的指针指向头,有两个指针分别指向头和尾。

c. 在默认情况下,容量为32,当添加元素时,需要扩容时,根据增长因子来扩容。

e. null也可以是一个元素。

7. HashTable

a. 每个类对应着一个唯一的hashCode,所以相当于自带key

b. hash表的目的是,可以有一个任意长度的数组,查找、增删都很快。

c. 它的思想是,对于该对象的hash值,经过一定的计算,得到它的地址。

d. 不同的对象,也就是不同的hash值经过计算,可能得到相同的地址,这就需要冲突避免机制,主要有开放寻址法(线性探寻、二次探查)和二次哈希,线性探寻是有冲突就将该值后移一位,二次探查是每次检查位置空间的不常为平方倍数,即不是后移一位,而是前移几位或者后移更多为位,以此循环。二次哈希是如果冲突了,就再经过一个类似的计算公式得到一个地址,来避免冲突。

e. 哈希表最佳的数据/地址比例为72%,当你赋这个值大于72%时,系统会自动改为72%,当需要扩容时,扩成双倍,所有的数据要重新哈希计算。为避免这种运算,最好提前估计哈希表的大小。

8. Dictionary<K,T>(推荐使用)

由于hash table只有冲突避免机制,没有冲突解决机制,而且扩容会造成大量计算,字典提出了解决冲突机制。

a. 它的值如果冲突时,就以链表的形式挂在原值的后面。这种一个位置可以有多个元素,这个有值的位置被称为桶。

b. 最好的情况就是没有需要挂在元素后面的元素,这样的话查找的复杂度为O(1)

c. 其实它也是用空间换时间的,每个字典至少是由三个位置的,而且都有两个数组来完成索引工作,当需要存储的数据特别小的时候,不要过多使用字典。

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值