5.C#集合与数组

数据结构

  • 数据结构是计算机存储、组织、管理数据的方式
  • 数据结构是指相互之间存在一种或多种特定关系的数据元素的集合

一、数组的定义

Array

也就是数组。具体表示方法是:数据类型[维数] 数组名=new 数据类型[]

数组有很多的优点,比如说数组在内存中是连续存储的,所以它的索引速度是非常的快,而且赋值与修改元素也很简单,

比如:

  //声明一个一维数组

 intArray1 = new int[3];

//初始化一个一维数组

intArray1 = new int[3]{1,2,3};

intArray1 = new int[]{1,2,3};

//赋值

s[0]="a";

s[1]="b";

s[2]="c";

//修改

s[1]="b1";

//声明一个二维数组

int[,] cells=int[3,3];  

int[,] cells={{1,0,2},{1,2,0},{1,2,1}};      //初始化一个二维整数数组   

数组的不足之处在于,使用数组管理数据时,需要预先知道数组长度。而实际开发中,很多数据往往是无法事先知道元素个数的。

数组是一种非常有用的数据结构,但数组也具有严重的局限性。

①数组元素的数据类型必须是相同的

②在创建数组时必须知道元素个数

③对应用程序来说,需要通过循环索引来访问元素。

 

 针对于数组的这些缺点,C#中最先提供了ArrayList对象来克服这些缺点。 

适应于知道数组长度并且在使用过程中不需要插入元素的情况。

 

ArrayList

动态数组,用法似乎跟c++的vector有点像。使用ArrayList必须引用Collections类。

用于数据存储和检索的专用类。它的大小是按照其中存储的数据来动态扩充与收缩的。所以,我们在声明ArrayList对象时并不需要指定它的长度。

ArrayList继承了IList接口,所以它可以很方便的进行数据的添加,插入和移除。比如:

ArrayList list = new ArrayList(); //新增数据

list.Add("abc"); list.Add(123); //修改数据

list[2] = 345; //移除数据

list.RemoveAt(0); //插入数据

list.Insert(0, "hello world");

添加

  • Add(a) 添加元素a到末尾;
  • Insert(b,a) 在位置b插入元素a;
  • InsertRange(b,a) 在位置b插入集合a;

删除

  • Remove(a) 移除元素a;
  • RemoveAt(a) 移除位置a的元素;
  • RemoveRange(a,b) 移除位置a到位置b的元素;
  • Clear() 清空;

排序 Sort();

反转 Reverse();

查找

  • IndexOf(a) 返回元素a的位置,没有则返回-1;
  • Contains(a) 检测是否含有元素a,返回true/false;

从上面示例看,ArrayList好像是解决了数组中所有的缺点,在list中,我们不仅插入了字符串"abc",而且又插入了数字123。这样在ArrayList中插入不同类型的数据是允许的。因为ArrayList会把所有插入其中的数据都当作为object类型来处理。这样,在我们使用ArrayList中的数据来处理问题的时候,很可能会报类型不匹配的错误,也就是说ArrayList不是类型安全的。

既使我们保证在插入数据的时候都很小心,都有插入了同一类型的数据,但在使用的时候,我们也需要将它们转化为对应的原类型来处理。这就存在了装箱与拆箱的操作,会带来很大的性能损耗。

穿插一下装箱与拆箱的概念: 简单的来讲: 装箱:就是将值类型的数据打包到引用类型的实例中 比如将int类型的值123赋给object对象o int i=123; object o=(object)i; 拆箱:就是从引用数据中提取值类型 比如将object对象o的值赋给int类型的变量i object o=123; int i=(int)o; 装箱与拆箱的过程是很损耗性能的。

ArrayList与Array的区别

  • Array大小是固定的,ArrayList大小可按需自动扩容。
  • Array的特点是类型统一且长度固定,ArrayList是可变长数组。
  • Array一次只能获取或设置一个元素的值,ArrayList允许添加、插入、移除某个范围的元素。
  • Array下限可自定义,ArrayList下限始终未0。
  • Array具有多维,ArrayList始终只有一维。
  • Array位于System命名空间中,ArrayList位于System.Collections命名空间中。
  • ArrayList是非泛型列表,可见任意Object类型作为元素。

 

二、集合的定义

数组并不是使用最为方便的数据结构。C#提供了集合,通过它来管理数据将更为方便。

C#提供了一系列特殊功能的类,这些类可存储任意类型的对象,且长度是可变的,统称为集合。C#编程语言中,集合结构分为泛型集合、非泛型集合。

常用集合

  • 数组 Array 
  • 列表 List:List<T>是与数组相当的集合类
  • 动态数组 ArrayList、List<T> 
  • 键值对集合
    • 哈希集合/哈希表 Hashtable 
    • 字典 Dictionary<K,V> 
  • 堆栈 Stack、Stack<T>,堆栈的特点是后进先出(LIFO, Last In First Out)。
  • 队列 Queue、Queue<T>,队列的特点是先进先出(FIFO, First In First Out)。
  • 可排序键值对:特点是插入、检索没有哈希表集合高效
    • 有序列键值对列表 SortedList、SortedList<K,V> 特点是占用内存更少,可通过索引访问。
    • 有序字典 SortedDictionary 特点是占用内存更多,没有索引,但插入和删除元素的速度比SortedList快。
  • Set集合:特点是无序、不重复。
    • HashSet<T>集合可将HashSet类视为不包含值得Dictionary集合,与List<T>类似。
    • SortedSet<T> 在.NET4.0支持,有序无重复的集合。
  • 双向链表集合:LinkedList<T>特点是增删速度快

 

理解泛型与非泛型的概念

1、BCL中集合类型分为泛型集合与非泛型集合。

2、非泛型集合的类和接口位于System.Collections命名空间。

3、泛型集合的类和接口位于System.Collections.Generic命名空间。

同传统的集合相比,泛型集合是一种强类型的集合,它解决了类型安全问题,同时避免了集合中每次的装箱与拆箱的操作,提升了性能。

       1. List,这是我们应用最多的泛型种类,它对应ArrayList集合。

2. Dictionary,这也是我们平时运用比较多的泛型种类,对应Hashtable集合。

3. Collection对应于CollectionBase

4. ReadOnlyCollection 对应于ReadOnlyCollectionBase,这是一个只读的集合。

5. Queue,Stack和SortedList,它们分别对应于与它们同名的非泛型类。

C#2.0后出现了List。

泛型集合:          
①List

List names = new List();

names.Add("乔峰");

names.Add("欧阳峰");

names.Add("马蜂");

foreach (string name in names)

{

Console.WriteLine(name);

}

//向List中插入元素

names.Insert(2, "张三峰");

//移除指定元素

names.Remove("马蜂"); 

②Dictionary

System.Collections.DictionaryEntry dic=new System.Collections.DictionaryEntry("key1","value1");

Dictionary fruit = new Dictionary(); //加入重复键会引发异常

fruit.Add(1, "苹果");

fruit.Add(2, "桔子");

fruit.Add(3, "香蕉");

fruit.Add(4, "菠萝"); //因为引入了泛型,所以键取出后不需要进行Object到int的转换,值的集合也一样

foreach (int i in fruit.Keys) {

Console.WriteLine("键是:{0} 值是:{1}",i,fruit);

}

//删除指定键值

fruit.Remove(1);

//判断是否包含指定键

if (fruit.ContainsKey(1)) {

Console.WriteLine("包含此键");

}

//清除集合中所有对象

fruit.Clear(); 

SortedList类 与哈希表类似,区别在于SortedList中的Key数组排好序的 

Stack类 栈,后进先出。push方法入栈,pop方法出栈。

Queue类 队列,先进先出。enqueue方法入队列,dequeue方法出队列。 

非泛型集合:

①Hashtable

Hashtable abc = new Hashtable();            

abc.Add("1", "34");      (key,value)      

if (abc.Contains("1"))            

{                

Response.Write(abc["1"]);            

Hashtable与Dictionary异同点

  1. 在单线程程序中推荐使用Dictionary,由于具有泛型优势且读取速度较快,其容量利用会更加充分。
  2. 在多线程程序中推荐使用Hashtable,默认的Hashtable允许单线程写入多线程读取,对Hashtable进一步调用Synchronized()方法可获得完全线程安全的类型。而Dictionary是非线程安全的,必须人为使用lock语句进行保护,其效率大减。
  3. 经过测试发现,但key是整型时Dictionary的操作效率要高于Hashtable,而当key是字符串时则Dictionary的效率并没有Hashtable的快。
  4. Dictionary有按插入顺序排列数据的特性,但是当调用Remove()方法删除节点后原来的顺序会被打乱掉。因此在需要体现顺序的场景中使用Dictionary能获得一定的便利。
  5. 遍历Dictionary时会采用插入时的顺序,而遍历Hashtable则是打乱掉的。

哈希表的遍历

哈希表的遍历使用foreach,由于哈希表中的元素是键值对,因此需要使用DictionaryEntry类型来进行遍历。DictionaryEntry类型表示一个键值对的集合。

Hashtable ht = new Hashtable();

ht.Add("UserID", 1);

ht.Add("UserNO", "BH0001");

ht.Add("UserName", "Tim");

ht.Add("UserGender", 1);       foreach(DictionaryEntry dic in ht){

Console.WriteLine($"{dic.Key} = {dic.Value}");}


②Queue

System.Collections.Queue queue=new System.Collections.Queue();

queue.Enqueue(1);

queue.Enqueue(2);

System.Console.WriteLine(queue.Peek());

while(queue.Count>0) {

System.Console.WriteLine(queue.Dequeue());

}

③SortedList

System.Collections.SortedList list=new System.Collections.SortedList();

list.Add("key2",2);

list.Add("key1",1);

for(int i=0;i0) {

System.Console.WriteLine(stack.Pop());

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值