c#常用的数据结构

Array数组

内存上连续存储,

数组是引用类型而不是值类型。

优点:

按照索引查询元素速度很快。

按照索引遍历数组很方便。

缺点:

声明数组时大小必须确定,且大小不能改变。

添加和删除元素的速度很慢,因为需要移动其它元素。

数组只能存储一种数据类型。

一维数组的声明和创建形式:

数组类型 [ ] 数组名 = new 数组类型 [数组长度]

int [ ] one = new int [5] { 1, 2, 3, 4, 5 };

相当于MFC 的CArray

二维数组

int [,] one = new int [2,3];

位数组 BitArray

ArrayList

ArrayList类相当于一种高级的动态数组,它是Array类的升级版本.本质是一个object类型的数组.ArrayList类是引用类型。连续的内存。在存和使用值类型的对象时或发生装箱/拆箱的操作。

using System .Collections ;

ArrayList List=new ArrayList();

ArrayList 转Array的函数

Array ToArray(Type type);

ArrayList List = new ArrayList();

for (int i = 0; i < 10; i++)

List.Add(i);

int[] values = (int[])List.ToArray(typeof(int)); //正确

List

List<T> 等效于ArrayList,性能比Arraylist高。 List的内部是用数组实现的,而不是链表,所以也是连续内存。当元素被添加到List中时,List的容量会根据需要自动增加,通过重新分配内部数组。

List<int> primeNumbers = new List<int>();

List 转Array的函数

List<int> primeNumbers = new List<int>();

for (int i = 0; i < 10; i++)

primeNumbers.Add(i);

int[] Numbers = primeNumbers.ToArray();

Array转 List 的函数

int [] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ,10};

List<int > list = new List<int >(array);

相当于 c++ 的vector

LinkedList(双向链表)

内存非连续的、非顺序的存储结构,无法通过下标查找元素,在查找链表元素时,总是从头结点开始查找;动态调整容量。

查询复杂度为 O(n),操作复杂度为 O(1)。

遍历:

LinkedListNode<int> nowNode=linkedList.First;

while(nowNode!=null)

{

nowNode=nowNode.Next;

}

或者

foreach(int item in linkedList)

{

Console.WriteLine(item);

}

Array转Linked List 的函数

int [] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ,10};

LinkedList<int > linkedList = new LinkedList<int >(array);

相当于c++的 list

Stack(栈)

栈是有顺序的,是一片连续的内存域,保持着先进后出的原则。

Stack<string> numbers = new Stack<string>();

numbers.Push("one");

string str = numbers.Peek(); //获取不出栈

str = numbers.Pop();//获取并出栈

Queue(队列)

先进先出,存在装箱拆箱,存储任意类型,无法获取指定位置元素,只能取出最先存储的元素。

Queue<string> queue = new Queue<string>();

//向队列中添加元素

ueue.Enqueue ("老一");

queue.Enqueue ("老二");

queue.Dequeue ();获取并移除队列中队首的元素

queue.Peek ();返回顶部的对象而不将其从 队列 中移除

HashSet

是基于哈希表的原理实现的,根据key直接访问存储位置的数据结构

无序、不重复;

插入、查找时间复杂度为O(1);

不使用索引;

容量不足时自动扩容,但扩容成本高;

HashSet<string> hashSet = new HashSet<string>();

hashSet.Add ("123");

hashSet.Add ("456");

//转换成List集合

hashSet.ToList();

相当于STL 的hash_set或者说unordered_set

SortedSet

基于红黑树实现,有序、不重复的集合

SortedSet<string> SortSet = new SortedSet<string>();

SortSet.Add ("123");

hashSet.Add ("456");

foreach (var index in SortSet)

{

}

//转换成List集合

SortSet.ToList();

相当于STL的set

Hashtable

基于哈希表实现,一系列基于键的哈希代码组织起来的 键/值对 。它使用键来访问集合中的元素。

特点:

key(键) 是唯一的,不可重复,

只能通过 key 查询对应 的value

Hashtable hashtable = new Hashtable();

hashtable.Add(0, 1);

hashtable.Add(1, 'a');

foreach (var key in hashtable.Keys)

{

var tablekey = key;

var value = hashtable[key];

}

相当于STL 的unordered_map (hash_map)

Dictionary(字典)

基于哈希表实现,字典中的key值是唯一的。

字典底层将数据储存在数组里面,通过哈希函数建立Key------Value的对应关系,利用拉链法处理哈希冲突。另外,字典是线程不安全的,如果需要线程安全,需要自己加锁

Dictionary<int, string> _testDic = new Dictionary<int, string>();

_testDic.Add (24, "Canon");

// 注意相同相同Key值只能Add一次

_testDic.Add (34, "Jason"); // foreach遍历

foreach (var kvp in _testDic)

{

Console .WriteLine ("Key = {0}, Value = {1}", kvp.Key , kvp.Value );

}

相当于STL 的unordered_map (hash_map)

Dictionary和Hashtable对比

Dictionary<K,V>是泛型的,当K或V是值类型时,其速度远远超过Hashtable。

由于 Hashtable 和 Dictionary 同时存在, 在使用场景上必然存在选择性, 并不任何时刻都能相互替代.
[1] 单线程程序中推荐使用 Dictionary, 有泛型优势, 且读取速度较快, 容量利用更充分.
[2] 多线程程序中推荐使用 Hashtable, 默认的 Hashtable 允许单线程写入, 多线程读取, 对 Hashtable 进一步调用 Synchronized() 方法可以获得完全线程安全的类型. 而 Dictionary 非线程安全, 必须人为使用 lock 语句进行保护, 效率大减.
[3] Dictionary 有按插入顺序排列数据的特性 (注: 但当调用 Remove() 删除过节点后顺序被打乱), 因此在需要体现顺序的情境中使用 Dictionary 能获得一定方便.

SortedDictionary

基于使用红黑树实现的键值对集合。

特点:

有序,键唯一

只能通过 key(键) 查询对应 的 value(值)

SortedDictionary 可对未排序的数据执行更快的插入和移除操作:它的时间复杂度为 O(log n)

SortedDictionary<int, string> My_sdict = new SortedDictionary<int, string>();

My_sdict.Add (004, "Ask.com");

My_sdict.Add (003, "Yahoo");

foreach (var kvp in My_sdict)

{

Console .WriteLine ("Key = {0}, Value = {1}", kvp.Key , kvp.Value );

}

相当于STL的map

SortedList

排序列表是数组和哈希表的组合,使用索引访问各项,则它是一个动态数组,如果您使用键访问各项,则它是一个哈希表。集合中的各项总是按键值排序。

总结

数据结构 类型及备注 插入和删除 查找
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(logN) O(logN)
SortedDictionary<K,T> 保存键值对、内部使用红黑树实现、保持有序、不定长 O(logN) O(logN)
HashSet<K> 使用开散列法、不定长、动态扩容、长度总为质数、是不含值的字典,故复杂度和它完全相同 O(1) O(1)
SortedSet<T> 内部使用红黑树实现、保持有序、不定长、是不含值的SortedDictionary<K,T>,故复杂度和它完全相同 O(logN) O(logN)

相关推荐
愿天垂怜17 分钟前
【C++】C++11引入的新特性(1)
java·c语言·数据结构·c++·算法·rust·哈希算法
淡写青春20922 分钟前
计算机基础---进程间通信和线程间通信的方式
java·开发语言·数据结构
特种加菲猫33 分钟前
初阶数据结构之栈的实现
开发语言·数据结构·笔记
bingw01141 小时前
华为机试HJ62 查找输入整数二进制中1的个数
数据结构·算法·华为
苏言の狗1 小时前
小R的二叉树探险 | 模拟
c语言·数据结构·算法·宽度优先
jianqimingtian1 小时前
如何使用 Matlab 制作 GrabCAD 体素打印切片
数据结构·数据库
gkdpjj2 小时前
C++优选算法十四 优先级队列(堆)
开发语言·数据结构·c++·算法
几窗花鸢2 小时前
力扣面试经典 150(上)
数据结构·c++·算法·leetcode
Heisenberg~3 小时前
详解八大排序(五)------(计数排序,时间复杂度)
c语言·数据结构·排序算法
小吴同学·7 小时前
.NET6 WebApi第1讲:VSCode开发.NET项目、区别.NET5框架【两个框架启动流程详解】
c#·.netcore·.net core