美文网首页
C# 常用数据结构

C# 常用数据结构

作者: 合肥黑 | 来源:发表于2022-01-27 20:08 被阅读0次
一、c#中的数组、ArrayList、List区别

在C#中数组,ArrayList,List都能够存储一组对象,那么这三者到底有什么样的区别呢。

  • (1)数组引入的命名空间:using System;
  • (2)Array:用法基本与数组同,引入命名空间:using System;
  • (3)ArrayList:引入命名空间: using System.Collections
  • (4)List:引入命名空间:using System.Collections.Generic;
1.数组

数组在C#中最早出现的。在内存中是连续存储的,所以它的索引速度非常快,而且赋值与修改元素也很简单。

//string[] s= {"a","b"};
string[] s=new string[2];  
  
//赋值  
s[0]="a";  
s[1]="b";  
//修改  
s[1]="a1";  

但是数组存在一些不足的地方。在数组的两个数据间插入数据是很麻烦的,而且在声明数组的时候必须指定数组的长度,数组的长度过长,会造成内存浪费,过段会造成数据溢出的错误。如果在声明数组时我们不清楚数组的长度,就会变得很麻烦。针对数组的这些缺点,C#中最先提供了ArrayList对象来克服这些缺点。

2.ArrayList

ArrayList是命名空间System.Collections下的一部分,在使用该类时必须进行引用,同时继承了IList接口,提供了数据存储和检索。ArrayList对象的大小是按照其中存储的数据来动态扩充与收缩的。所以,在声明ArrayList对象时并不需要指定它的长度。

ArrayList list1 = new ArrayList();  
//新增数据  
list1.Add("cde");  
list1.Add(5678);  
//修改数据  
list[2] = 34;  
//移除数据  
list.RemoveAt(0);  
//插入数据  
list.Insert(0, "qwe");  

从上面例子看,ArrayList好像是解决了数组中所有的缺点,为什么又会有List?

我们从上面的例子看,在List中,我们不仅插入了字符串cde,而且插入了数字5678。这样在ArrayList中插入不同类型的数据是允许的。因为ArrayList会把所有插入其中的数据当作为object类型来处理,在我们使用ArrayList处理数据时,很可能会报类型不匹配的错误,也就是ArrayList不是类型安全的。在存储或检索值类型时通常发生装箱和取消装箱操作,带来很大的性能耗损。

装箱与拆箱的概念:

装箱:就是将值类型的数据打包到引用类型的实例中 比如将string类型的值abc赋给object对象obj

String  i=”abc”;
object obj=(object)i;

拆箱:就是从引用数据中提取值类型:比如将object对象obj的值赋给int类型的变量j

object obj=”abc”;
int j = (int)obj;//拆箱:将引用类型的obj转化为值类型j;

补充:
Array的用法与数组几乎一样,可以看做是数组。在定义的时候需要指定长度;ArrayList的用法与普通集合一样,定义的时候不需要指定长度;如:

Array[] animalArray = new Array[2];
ArrayList animalArrayList = new ArrayList();
3.泛型List

因为ArrayList存在不安全类型与装箱拆箱的缺点,所以出现了泛型的概念。List类是ArrayList类的泛型等效类,它的大部分用法都与ArrayList相似,因为List类也继承了IList接口。最关键的区别在于,在声明List集合时,我们同时需要为其声明List集合内数据的对象类型。

list = new List<string>();  
//新增数据  
list.Add(“abc”);  
//修改数据  
list[0] = “def”;  
//移除数据  
list.RemoveAt(0);  

上例中,如果我们往List集合中插入int数组123,IDE就会报错,且不能通过编译。这样就避免了前面讲的类型安全问题与装箱拆箱的性能问题了。

二、C# ArrayList、HashSet、HashTable、List、Dictionary的区别详解

HashTable是一种根据key查找非常快的键值数据结构,不能有重复key,而且由于其特点,其长度总是一个素数,所以扩容后容量会比2倍大一点点,加载因子为0.72f。

当要大量使用key来查找value的时候,HashTable无疑是最有选择,HashTable与ArrayList一样,是非泛型的,value存进去是object,存取会发生装箱、拆箱,所以出现了Dictionary。

Dictionary是HashTable的泛型版本,存取同样快,但是不需要装箱和拆箱了。而且,其优化了算法,Hashtable是0.72,它的浪费容量少了很多。

1.HashTable
using System;
using System.Collections;

namespace CollectionsApplication
{
   class Program
   {
      static void Main(string[] args)
      {
         Hashtable ht = new Hashtable();


         ht.Add("001", "Zara Ali");
         ht.Add("002", "Abida Rehman");
         ht.Add("003", "Joe Holzner");
         ht.Add("004", "Mausam Benazir Nur");
         ht.Add("005", "M. Amlan");
         ht.Add("006", "M. Arif");
         ht.Add("007", "Ritesh Saikia");

         if (ht.ContainsValue("Nuha Ali"))
         {
            Console.WriteLine("This student name is already in the list");
         }
         else
         {
            ht.Add("008", "Nuha Ali");
         }
         // 获取键的集合 
         ICollection key = ht.Keys;

         foreach (string k in key)
         {
            Console.WriteLine(k + ": " + ht[k]);
         }
         Console.ReadKey();
      }
   }
}

001: Zara Ali
002: Abida Rehman
003: Joe Holzner
004: Mausam Benazir Nur
005: M. Amlan
006: M. Arif
007: Ritesh Saikia
008: Nuha Ali 
2.Dictionary
//Persion.cs
using System;

namespace SampleList
{
    class Person
    {
        public string name;
        public int age;

        //构造函数
        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }
    }
}

//CustomDictionary.cs
using System;
using System.Collections.Generic;

namespace SampleList
{
    class CustomDictionary
    {

        //定义一个字典变量
        static Dictionary<int, Person> dicPerson = new Dictionary<int, Person>();

        public static void LearnDictionaryInfo()
        {
            //添加键值 
            Person p1 = new Person("hjc", 22);
            Person p2 = new Person("tf", 21);
            dicPerson.Add(0, p1); //方式1
            dicPerson[1] = p2;    //方式2

            //取值
            Console.WriteLine("\n");
            Console.WriteLine("取值  name:" + dicPerson[0].name + "—" + "age:" + dicPerson[0].age);

            //改值
            Console.WriteLine("\n");
            dicPerson[1].age = 20;
            Console.WriteLine("改值  name:" + dicPerson[1].name + "—" + "age:" + dicPerson[1].age);

            //遍历key
            Console.WriteLine("\n");
            Console.WriteLine("遍历 key");
            foreach (int key in dicPerson.Keys)
            {
                string id = "用户ID:" + key;
                string str = string.Format("name:{0} age:{1}", dicPerson[key].name, dicPerson[key].age);
                Console.WriteLine(id + "\t" + str);
            }

            //遍历value
            Console.WriteLine("\n");
            Console.WriteLine("遍历 value");
            foreach (Person value in dicPerson.Values)
            {
                string str = string.Format("name:{0} age:{1}", value.name, value.age);
                Console.WriteLine(str);
            }

            //遍历字典
            Console.WriteLine("\n");
            Console.WriteLine("遍历字典");
            foreach (KeyValuePair<int, Person> kvp in dicPerson)
            {
                string str = string.Format("key:{0}/name:{1}/age:{2}", kvp.Key, kvp.Value.name, kvp.Value.age);
                Console.WriteLine(str);
            }

            //  删除元素
            Console.WriteLine("\n");
            Console.WriteLine("删除元素");
            if (dicPerson.ContainsKey(1))    //如果存在
                dicPerson.Remove(1);
            foreach (Person value in dicPerson.Values)
            {
                string str = string.Format("name:{0} age:{1}", value.name, value.age);
                Console.WriteLine(str);
            }
            //清除所有的元素
            dicPerson.Clear();

            Console.Read();
        }

    }
}
3.HashSet

HashSet类,算法,存储结构都与哈希表相同,主要是设计用来做高性能集运算的,例如对两个集合求交集、并集、差集等。集合中包含一组不重复出现且无特定顺序的元素。

参考
如何使用 C# 中的 HashSet

所谓的HashSet,指的就是 System.Collections.Generic 命名空间下的 HashSet<T> 类,它是一个高性能,无序的集合,因此HashSet它并不能做排序操作,也不能包含任何重复的元素,Hashset 也不能像数组那样使用索引,所以在 HashSet 上你无法使用 for 循环,只能使用 foreach 进行迭代,HashSet 通常用在处理元素的唯一性上有着超高的性能。

HashSet<T> 实现了如下几个接口:


public class HashSet<T> : System.Collections.Generic.ICollection<T>,
System.Collections.Generic.IEnumerable<T>, 
System.Collections.Generic.IReadOnlyCollection<T>,
System.Collections.Generic.ISet<T>,
System.Runtime.Serialization.IDeserializationCallback,
System.Runtime.Serialization.ISerializable
{
}

HashSet 只能包含唯一的元素,它的内部结构也为此做了专门的优化,值得注意的是,HashSet 也可以存放单个的 null 值,可以得出这么一个结论:如何你想拥有一个具有唯一值的集合,那么 HashSet 就是你最好的选择,何况它还具有超高的检索性能。


        static void Main(string[] args)
        {
            HashSet<string> hashSet = new HashSet<string>();
            hashSet.Add("A");
            hashSet.Add("B");
            hashSet.Add("C");
            hashSet.Add("D");
            if (hashSet.Contains("D"))
                Console.WriteLine("The required element is available.");
            else
                Console.WriteLine("The required element isn’t available.");
            Console.ReadKey();
        }

如果你向 HashSet 中插入重复的元素,它的内部会忽视这次操作而不像别的集合一样抛出异常,接下来展示一下代码:


        static void Main(string[] args)
        {
            HashSet<string> hashSet = new HashSet<string>();
            hashSet.Add("A");
            hashSet.Add("B");
            hashSet.Add("C");
            hashSet.Add("D");
            hashSet.Add("D");
            Console.WriteLine("The number of elements is: {0}", hashSet.Count);//4
            Console.ReadKey();
        }
4.Queue、Queue

Queue队列,Queue泛型队列,大学都学过,队列,先进先出,很有用。

5.Stack、Stack

Stack堆栈,先进后出。

6.SortedList、SortedList

SortedList集合中的数据是有序的。可以通过key来匹配数据,也可以通过int下标来获取数据。

添加操作比ArrayList,Hashtable略慢;查找、删除操作比ArrayList快,比Hashtable慢。

7.SortedDictionary

SortedDictionary相比于SortedList其性能优化了,SortedList其内部维护的是数组而SortedDictionary内部维护的是红黑树(平衡二叉树)的一种,因此其占用的内存,性能都好于SortedDictionary。唯一差在不能用下标取值。

8.ListDictionary(单向链表),LinkedList(双向链表)

,ArrayList,Hashtable等容器类,其内部维护的是数组Array来,ListDictionary和LinkedList不用Array,而是用链表的形式来保存。链表最大的好处就是节约内存空间。

ListDictionary是单向链表。

LinkedList双向链表。双向链表的优势,可以插入到任意位置。

参考C#LinkedList<T>链表

static void Main(string[] args)
{
    LinkedList<int> a = new LinkedList<int>();   //创建一个链表
    a.AddFirst(3);                         //在一开始添加一个节点
    a.AddLast(1);                          //在最后添加一个节点
    a.AddLast(4);                          //在最后添加一个节点

    foreach (int i in a)
        Console.Write(i + " ");            //输出3 1 4
    Console.WriteLine();

    LinkedListNode<int> cur = a.Find(3);   //cur对应3所在的第一个位置
    if (cur != null)
    {
        a.AddAfter(cur, 2);                //在3后面添加2
        a.AddBefore(cur,5);                //在3前面添加5
    }

    foreach (int i in a)
        Console.Write(i + " ");            //输出5 3 2 1 4
    Console.WriteLine();

    Console.WriteLine(cur.Next.Value);     //cur当前为3的位置,所以下一个为2
    Console.WriteLine(cur.Next.Previous.Value);  //3的下一个为2,2的上一个仍然为3
    Console.WriteLine(cur.Previous);       //Previous为上一个节点

    a.RemoveFirst();
    foreach (int i in a)
        Console.Write(i + " ");            //返回3 2 1 4
    Console.WriteLine();

    a.RemoveLast();
    foreach (int i in a)
        Console.Write(i + " ");            //返回3 2 1 
    Console.WriteLine();

    a.Remove(3);                           //删除值为3的节点,成功返回true,否则false
    a.Clear();                             //清空所有的节点

    Console.Read();
}
9.HybridDictionary

HybridDictionary的类,充分利用了Hashtable查询效率高和ListDictionary占用内存空间少的优点,内置了Hashtable和ListDictionary两个容器,添加数据时内部逻辑如下:

当数据量小于8时,Hashtable为null,用ListDictionary保存数据。

当数据量大于8时,实例化Hashtable,数据转移到Hashtable中,然后将ListDictionary置为null。

10.BitArray

BitArray这个东东是用于二进制运算,"或"、"非"、"与"、"异或非"等这种操作,只能存true或false;

相关文章

  • c#常用数据结构

    1.集合 List:将一推数据类型相同的数据放入到一个容器内,该容器就是集合,内存中开辟的一连串空间。 特点: 1...

  • C# 常用数据结构

    一、c#中的数组、ArrayList、List区别[https://www.cnblogs.com/newcape...

  • c#常用数据结构解释

    一,数组 Array 特点:数组存储在连续的内存上;数组的内容类型都相同;数组可以通过下面进行直接访问;创建过程:...

  • C# 常用的数据结构

    常用的数据结构

  • C# 常用数据结构总结

    表1 表2 表3 标"--"的是我目前并不清楚

  • 【数据结构】【C#】012-队列应用:💻键盘缓冲

    C#数据结构:队列应用:键盘输入循环缓冲区问题 在操作系统中,循环队列经常用于实时应用程序。例如,当程序正在执行其...

  • unity & C#相关

    事件和委托 C#事件和Unity3d - CSDN博客 Unity常用的函数和遇到的C#的知识整理 Unity常用...

  • C#类型

    《C#图解教程》学习记录 C#程序是一组类型声明。类型是一种用来创建数据结构的模板。 预定义类型 C#提供了16种...

  • Java数据结构(1)

    常用数据结构 Java中常用的数据结构主要分为Collection和Map接口。Collection下分为List...

  • C#中常用的数据结构(转)

    前言:可能去过罗小黑博客的盆油们读过这篇对于数据结构的总结,但是罗小黑当时写那篇文章的时候略有匆忙,所以今天进行了...

网友评论

      本文标题:C# 常用数据结构

      本文链接:https://www.haomeiwen.com/subject/kuxtzltx.html