自学内容网 自学内容网

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转LinkedList的函数

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)


原文地址:https://blog.csdn.net/baidu_16370559/article/details/136224355

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!