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 = hashtablekey;

}

相当于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)

相关推荐
ytttr87330 分钟前
C# 定时数据库备份工具
开发语言·数据库·c#
dtq04241 小时前
C语言刷题数组5,6(求平均值,求最大值)
c语言·数据结构·算法
雪豹阿伟2 小时前
21.Winfrom —— 定时器、日期选择器、进度条、表格、DataTable
c#·上位机·winfrom
z落落2 小时前
C#WinForm控件实战:Panel与单选框动态创建
开发语言·c#
洛水水2 小时前
【力扣100题】81.寻找两个正序数组的中位数
数据结构·算法·leetcode
Coder-magician3 小时前
《代码随想录》刷题打卡day15:二叉树part05
数据结构·c++·算法
Darling噜啦啦3 小时前
二叉树与递归算法实战:从树结构到 LeetCode 爬楼梯,一文吃透前端数据结构与递归思维
前端·javascript·数据结构
Irissgwe3 小时前
算法的时间复杂度和空间复杂度
数据结构·c++·算法·c·时间复杂度·空间复杂度
qq_297574674 小时前
设计模式系列文章(基础篇第22篇):访问者模式——分离数据结构与操作,实现灵活扩展
数据结构·设计模式·访问者模式
云淡风轻~窗明几净4 小时前
角谷猜想的任意算法测试
数据结构·人工智能·算法