第6章数组和集合•数组是C#程序设计中最常使用的类型之一。•数组能够按一定规律把相关的数据组织在一起,能通过“索引”或“下标”快速地管理这些数据。•集合是指一组类似的对象。在C#中,任意类型的对象都可以放入一个集合中,并将其视为Object类型。•C#开发大量使用集合的原因在于:一方面,世界中的很多问题需要使用集合来描述;另一方面,C#提供了强大的集合操作能力。•本章将介绍有关数组和集合的概念和应用。6.1数组•数组(Array)是一组相关数据的集合,在C#中应用较为广泛。本节将介绍数组的概念及应用。•6.1.1数组简介•“需购物品”清单:油、盐、酱、醋、毛毛熊。它规律地列出了其内部的数据,且其内部数据具有相同的性质。•在C#中,可以称这样一个清单为数组:string[]myStrArr={油,盐,酱,醋,毛毛熊};6.1.1数组简介•数组即一组数据,把一系列数据组织在一起,成为一个可操作的整体。•在数组中的每一个元素对应排列次序下标。当使用其中的某个元素时,可以直接利用这个次序下标,例如:1.for(inti=0;imyStrArr.Length;i++)2.{3.Console.WriteLine(item{0}:{1},i,myStrArr[i]);4.}•将输出数组myStrArr中所有的元素。6.1.2创建数组•C#中的数组分为三种:一维数组、多维数组、交错数组。•一维数组:数组中的每个数据都只有一个元素。•例:int[]a=newint[10];//整数数组string[]s=newstring[20];//字符串数组String[]t=newString[30];//字符串类数组int[]b=newint[]{2,4,6};//3个元素的数组int[]c=newint[3]{2,4,6};//3个元素的数组6.1.2创建数组•多维数组:每个数据都由多个元素组成。例:int[,]a=newint[3,5];//整数数组。3行5列•数组形状如下图所示:***************•其他例:string[,,]s=newstring[2,3,5];//2*3*5维int[,]b=newint[,]{{1,3,5},{2,4,6}};//2行3列•多维数组特征:每维(如行、列、……)的长度相同。•交错数组:每维(如行、列、……)的长度可不相同。6.1.2创建数组•交错数组:各个维度长度不同的多维数组,也称为“数组的数组”。例:int[][]a=newint[3][];//3行?列a[0]=newint[5];//该行有5列a[1]=newint[4];//该行有5列a[2]=newint[2];//该行有2列•数组形状如下图所示:***********6.1.3访问数组(读、写)•通过下标定位元素:int[]b=newint[]{2,4,6};//3个元素的数组for(inti=0;i3;i++)Console.WriteLine(b[i]);•使用GetValue(读)/SetValue(写):int[]b=newint[3]{2,4,6};//3个元素的数组b.SetValue(89,2);//下标为2的元素修改为89for(inti=0;i3;i++)Console.WriteLine(b.GetValue(i));•获得数组下标(索引)的边界:GetLowerBound():下标最小值GetUpperBound():下标最大值6.1.4数组排序•数组排序:是指按照一定的排序规则,如递增或递减规则,重新排列数组中的所有元素。•可以使用Array类的Sort方法完成这个功能。Sort方法有多种重载方式,常用的形式如下:publicstaticvoidSort(Arrayarray);•其中,参数array为待排序的数组。•下面的示例首先定义了一个数组,含有元素{5,4,3,2,1},然后利用Sort方法对其排序:6.1.4数组排序•publicvoidtest1()•{•int[]myArr={5,4,3,2,1};//定义数组•//输出原始数组:原始数组:5-4-3-2-1-•Console.WriteLine(原始数组:);•for(inti=0;imyArr.Length;i++)•Console.Write({0}-,myArr[i]);•Array.Sort(myArr);//对数组排序•//并输出排序后的数组:1-2-3-4-5-•Console.WriteLine(排序以后数组:);•for(inti=0;imyArr.Length;i++)•Console.Write({0}-,myArr[i]);•}6.1.5数组应用的实例•本节将利用上一章和本章所介绍的字符串和数组操作技术,实现一个完整的示例:我的书房之图书排序。其功能为按照一定的排列顺序显示一系列图书信息。•书名价格作者–我的2010,20,王–家庭烹饪技术,18.23,张–西方哲学史,34.99,周–三侠五义,11.45,吴–象棋23式,122.50,鲍“•课本P88程序代码。6.2集合•数组是一种非常有用的数据结构,但是数组也具有严重的局限性:–数组元素的数据类型必须相同–在创建数组时必须知道有多少个元素,对应用程序来说,还需要通过循环索引来访问这些元素。•C#提供了集合,通过它来管理数据将更为方便。6.2.1集合的概念•集合是通过高度结构化的方式存储任意对象的类。•集合不仅能随意调整大小,而且对存储或检索存储在其中的对象提供了更高级的方法。•集合可以把一组类似的类型化对象组合在一起。•对于一个Object类型的集合来说,可能需要单独对各元素执行附加的处理,例如,装箱、拆箱或转换等。6.2.2集合类•常用集合包括数组、列表、哈希表、字典、队列和堆栈等基本类型,还包括有序列表、双向链表和有序字典等派生集合类型。常用的集合类见下表。集合含义Array数组List列表ArrayList动态数组Hashtable哈希表Dictionary字典(键/值对集合)Queue队列Stack栈SortedList有序键/值对列表LinkedList双向链表SortedDictionary有序字典6.2.3ArrayList动态数组类•ArrayList是一种较为复杂的数组,其实现了可变大小的一维数组。•1.创建ArrayListArrayListarr1=newArrayList();//创建动态数组。初始容量默认为16。ArrayListarr2=newArrayList(100);//创建容量为100的动态数组。•注意:在C#中,数组也是属于集合的一种。这里的集合跟数学意义上的集合不同!6.2.3ArrayList动态数组类•2.添加元素–Add:添加一个元素。–AddRange:添加多个元素。•3.删除元素–Remove:删除第一个匹配元素。–RemoveAt:删除指定元素。–RemoveRange:删除多个元素。•4.查找元素–BinarySearch:二分查找。6.2.4遍历列表•1.使用foreach语句遍历列表是指访问一遍列表中的所有元素,可以使用foreach语句完成这个功能。•2.使用GetEnumerator方法除了foreach之外,还可以使用ArrayList的GetEnumerator方法实现列表的遍历。形式如下:publicvirtualIEnumeratorGetEnumerator();GetEnumerator方法返回整个ArrayList的枚举数对象IEnumerator。这个对象可以得到一个集合对象的所有元素,其最主要的属性为Current,用于获取集合中的当前元素。6.4队列•队列(Queue):先进先出表。•入队操作Enqueue和出队操作Dequeue。6.4.1创建队列•利用Queue的构造函数创建一个新的队列,常用的形式包括以下几种:•(1)publicQueue()•(2)publicQueue(intcapacity)•(3)publicQueue(intcapacity,floatgrowFactor)•参数capacity可以指定所创建列表的初始容量,如果不指定,则初始容量为.NET的默认值32。而参数growFactor则指定当队列满后容量的增长率,新容量等于当前容量与growFactor的乘积,默认值为2.0。6.4.2元素入队•Enqueue实现向一个元素的入队操作。语法:publicvirtualvoidEnqueue(objectobj);•下面的示例中,首先定义了一个队列queue1,然后使用Enqueue方法,向其中添加了3个元素,其中第一个为字符串对象“Hello”,第二个为一个整数对象1,第3个为整型数组arr1。•1.Queuequeue1=newQueue();•3.//字符串:Hello入队•4.objectitem=newobject();•5.item=Hello;•6.queue1.Enqueue(item);•7.//整数:1入队•8.item=1;•9.queue1.Enqueue(item);•10.//数组:arr1={1,2,3}入队•11.int[]arr1=newint[]{1,2,3};•12.queue1.Enqueue(arr1);6.4.3元素出队•Dequeue实现一个元素的出队操作。语法:publicvirtualobjectDequeue();•下面的示例中,首先定义了一个队列queue1,然后使用Enqueue方法,依次入队3个元素。然后再使用Dequeue方法,输出所有的元素。注意,这个输出的顺序和入队的顺序是一致的。•1.Queuequeue1=newQueue();•3.//依次入队:Hello、1、{1,2,3}•4.queue1.Enqueue(Hello);•5.queue1.Enqueue(1);•6.queue1.Enqueue(newint[]{1,2,3});•8.//通过出队操作,队列元素输出顺序与入队的顺序一致•9.objectoutItem=newobject();•10.while(queue1.Count0)•11.{•12.outItem=queue1.Dequeue();•13.Console.WriteLine({0},outItem);•14.}6.5堆栈•堆栈(Stack):后进先出表。•最主要的方法为入栈操作Push和出栈操作Pop。6.5.1创建堆栈•利用Stack的构造函数创建一个新的堆栈,常用的形式包括:•(1)publicStack();•(2)publicStack(intcapacity)。•参数capacity可以指定所创建列表的初始容量。如果不指定,则初始容量为.NET的默认值10。当堆栈中的元素达到其最大容量时,容量将自动增加一倍。下面的代码创建了两个堆栈对象:•1.StackStack1=newStack();•2.StackStack2=newStack(100);6.5.2元素入栈•通过Push实现一个元素的入栈操作语法:publicvirtualvoidPush(objectobj);•下面的示例中,首先定义了一个堆栈Stack1,然后使用Push方法,向其中添加了3个元素,其中第一个为字符串对象“Hello”,第二个为一个整数对象1,第3个为整型数组arr1。•1.Stackstack1=newStack();•3.//字符串:Hello入栈•4.objectitem=newobject();•5.item=Hello;•6.stack1.Push(item);•7.//整数:1入栈•8.item=1;•9.stack1.Push(item);•10.//数组:arr1={1,2,3}入栈•11.int[]arr1=newint[]{1,2,3};•12.stack1.Push(arr1);6.5.3元素出栈•通过St