数据结构与算法----学习记录(贰)

第 2  章  数组和 ArrayLists

数组是最通用的数据结构,它出现在几乎所有的编程语言里。在 C#语言中使用数组包括创建 System.Array 类型的数组对象,以及创建针对所有数组的抽象的基类型。Array 类提供了一套方法,这些方法是为了执行诸如排序和查找这类过去需要程序员手工实现的任务。

C#语言中另外一种使用数组的有趣替换方式就是 ArrayList 类。ArrayList 是一种像要更多空间来动态生长的数组。对于无法精确知道数组最终大小的情况,或者对于程序生命周期内数组大小可能会发生一点变化的情况,用 ArrayList比用数组更合适。

2.1 数组基本概念

数组是可索引的数据的集合。数据既可以是内置的类型,也可以是用户自定义的类型。事实上,把数组数据称为对象大概是最简便的方式。C#语言中的数组实际上就是对象本身,因为它们都来源于 System.Array 类。既然数组是System.Array 类的一个声明实例,所以在使用数组时也可以使用此类的所有方法和属性。

2.1.1 数组的声明和初始化

          //声明
            string[] nameArr;

            //初始化1
            nameArr = new string[5];
            //初始化2
            nameArr = new string[] {"1","2","3","4","5" };

2.1.2 数组元素的设置和存取访问

存储数组元素既可以采用直接存取访问的方法也可以通过调用 Array 类的 SetValue 方法。直接存取方式通过赋值语句左侧的索引来引用数组位置:

而 SetValue 方法则提供了一种更加面向对象的方法来为数组元素赋值。这种方法会取走两个参数,一个是索引数,另一个则是元素的值。

数组元素的访问既可以通过直接存取的方式也可以通过调用 GetValue 方法的方式。GetValue 方法取走单独一个参数——即索引。

为了存取每一个数组元素用 For 循环来循环遍历数组是一种通用的方法。

 static void Main(string[] args)
        {
            int[] intArr = new int[10];
            intArr[2] = 2;

            intArr.SetValue(3,3);
            Console.WriteLine(intArr[3]);
            Console.WriteLine(intArr.GetValue(3));

        }

2.1.3  取回数组元数据的方法和属性

Array 类为取回数组元数据提供了几种属性:

  1. Length:返回数组所有维数内元素的总数量。
  2. GetLength:返回数组指定维数内元素的数量。
  3. Rank:返回数组的维数。
  4. GetType:返回当前数组实例的类型。

Length 方法对于计算多维数组中元素的数量以及返回数组中元素的准确编号都是很有用的。另外,还可以使用GetUpperBound 方法,而且要对数值加一。

既然 Length 返回数组元素的总数量,所以 GetLength 方法统计了数组某一维内元素的数量。这种方法和 Rank属性一起可用来在运行时调整数组的大小,而且不必冒丢失数据的风险。

在无法确定数组类型的情况下,GetType 方法可以用来确定数组的数据类型,比如数组作为参数传递给方法的时候。

2.1.4 多维数组

到目前为止的讨论只限于一维数组的情况。在 C#语言中,尽管数组多于三维的情况是非常少见的(而且也是非常容易使人混乱的),但是数组还是可以达到 32 维的。

通过提供数组每一维上限值的方式可以声明多维数组。二维数组的声明:int [ , ] grades = new int [4,5] ;此语句声明了一个 4 行 5 列的数组。二维数组经常用来模拟矩阵。

声明多维数组也可以不指定维数的上限值。要想这样做就要用到逗号来明确数组的维数。例如,声明一个二维数组如下所示
double [ , ] Sales ;再比如声明一个三维数组,double [ , , ] Sales ;

在声明不带维数上限的数组的时候,需要稍后对具有这类上限的数组重新确定维数:sales = new double [4,5] ;

  int[,] grades = new int[,]
            {
                { 1,11,111,1111},
                { 2,22,222,2222},
                { 3,33,333,3333},
                { 4,44,444,4444}
            };

首先要注意这里没有指明数组的上限。当初始化带有初始化表的数组的时候,不用说明数组的上限。编译器会根据初始化表中数据计算出每一维的上限值。初始化表本身也像数组的每一行那样用大括号进行标记。数组行内的每一个元素则用逗号进行分割。

存取访问多维数组元素的方法类似于存取一维数组元素的方法。大家可以采用传统的数组存取访问方式,也可以采用 Array 类的方法:getvalue,但是,对多维数组不能使用 SetValue 方法。这是因为这种方法只接收两个参数:一个数值和一个单独的索引。

2.1.5 参数数组

大多数的方法定义要求一套提供给方法的参数的数目,但是想要编写一个允许可选参数数目的方法定义是需要时间的。用一种称为参数数组的构造就可以做到。过使用关键字 ParamArray 就可以在方法定义的参数列表中指明参数数组。下面的方法定义允许提供任意数量的数作为参数,并且方法会返回数的总量:

 static void Main(string[] args)
        {
            int total1 = SunNums(1, 2, 3);
            int total2 = SunNums(1, 2, 3, 4, 5, 6, 7, 8);
            Console.WriteLine(total1);
            Console.WriteLine(total2);
        }
        static int SunNums(params int[] intArr)
        {
            int sum = 0;
            for (int i = 0; i <= intArr.GetUpperBound(0); i++)
            {
                sum += intArr[i];
            }
            return sum;
        }

当用参数数组定义方法的时候,为了使编译器能够正确处理参数列表,需要在参数列表的最后提供参数数组的
参数。否则,编译器无法知道参数数组元素的截止位置以及方法其他参数的起始位置。

2.2ArrayList 类

当无法提前知道数组的大小或者在程序运行期间数组的大小可能会发生改变的时候,静态数组就不是很适用了。这类问题的一种解决方案就是当数组超出存储空间的时使用能够自动调整自身大小的数组类型。这种数组被称为是 ArrayList。它是.NET 框架库中 System.Collections 命名空间的内容。

ArrayList 对象拥有可存储数组大小尺寸的 Capacity 属性。该属性的初始值为 16。当 ArrayList 中元素的数量达到此界限值时,Capacity 属性就会为 ArrayList 的存储空间另外增加 16 个元素。在数组内元素数量有可能扩大或缩小的情况下使用 ArrayList 会比用带标准数组的 ReDim Preserver 更加有效。

ArrayList 用 Object 类型来存储对象。如果需要强类型的数组,就应该采用标准数组或者其他一些数据结构。

2.2.1ArrayList 类成员

ArrayList 类包含几种用于 ArrayList 的方法和属性。下面这个列表就是最常用到的一些方法和属性:

  1. Add( ):向 ArrayList 添加一个元素。
  2. AddRange( ):在 ArrayList 末尾处添加群集的元素。
  3. Capacity:存储 ArrayList 所能包含的元素的数量。
  4. Clear( ):从 ArrayList 中移除全部元素。
  5. Contains( ):确定制定的对象是否在 ArrayList 内。
  6. Copy To( ):把 ArrayList 或其中的某一段复制给一个数组。
  7. Count:返回 ArrayList 中当前元素的数量。
  8. GetEnumerator( ):返回迭代 ArrayList 的计数器。
  9. GetRange( ):返回 ArrayList 的子集作为 ArrayList。
  10. IndexOf( ):返回指定数据项首次出现的索引。
  11. Insert( ):在 ArrayList 的指定索引处插入一个元素。
  12. InsertRange( ):从 ArrayList 指定索引处开始插入群集的元素。
  13. Item( ):在指定索引处获取或者设置一个元素。
  14. Remove( ):移除指定数据项的首次出现。
  15. RemoveAt( ):在指定索引处移除一个元素。
  16. Reverse( ):对 ArrayList 中元素的顺序进行反转。
  17. Sort( ):对 ArrayList 中的元素按照阿拉伯字母表顺序进行排序。
  18. ToArray( ):把 ArrayList 的元素复制给一个数组。
  19. TrimToSize( ):为 ArrayList 中元素数量设置 ArrayList 的容量。

2.2.2  应用 ArrayList 

ArrayList 的使用不同于标准数组。除非事出有因要把数据项添加到特殊位置上,否则通常情况下使用 Add 方法只是向 ArrayList 添加数据项,而对于上述特殊情况就要采用 Insert 方法来进行操作了。

首先要做的事情就是如下所示那样声明 ArrayList:

注意此声明中使用到了构造器。如果 ArrayList 没有声明使用构造器,那么在后续程序语句里就无法获得对象。用 Add 方法把对象添加给 ArrayList。此方法会取走一个参数,即添加给 ArrayList 的对象。Add 方法也会返回一个整数用来说明 ArrayList 中被添加元素的位置,当然这个值是很少会在程序中用到的。下面是一些实例:

   ArrayList al = new ArrayList();
            al.Add(9);
            al.Add(10);
            int pos;
            pos = al.Add(11);
            Console.WriteLine("The al 11 add Pos:"+pos);

如果需要在 ArrayList 某个特殊位置上添加元素,则可以采用 Insert 方法。此方法会取走两个参数:插入元素的索引,以及要插入的元素。 al.Insert(3,8);

通过调用 Capacity 属性可以检查 ArrayList 当前的容量,而通过调用 Count 属性可以确定 ArrayList 中元素的数量:

这里有几种从 ArrayList 中移除数据项的方法。如果知道要移除的数据项,但又不确定它所处的位置,那么就可以采用 Remove 方法。此方法会取走一个参数,即要从 ArrayList 中移除的对象。如果 ArrayList 内有这个对象,就可以把它移除掉。如果此对象不在 ArrayList 内,那就什么也不做。当使用像 Remove 这样的方法时,典型做法是把方法放置在 If-Then 语句内进行调用,并且使用诸如 Contains 这样的方法来验证对象确实存在 ArrayList 内。

如果知道所要移除数据项的索引,那么可以使用 RemoveAt 方法。此方法会取走一个参数,即要移除对象的索引。唯一能接受的人为错误就是给方法传递一个无效的索引。

通过调用 IndexOf 方法可以确定 ArrayList 中某个对象的位置。这种方法会取走一个参数,即一个对象,然后返回此对象在 ArrayList 内的位置。如果对象不在 ArrayList 内,那么方法就会返回-1。

除了向 ArrayList 中添加单独的对象,还可以添加对象的范围。对象必须存储在来源于 ICollection 的数据类型里面。这就意味着可以把对象存储在数组里,或存储在 Collection 里,甚至是存储到另一个 ArrayList 里面。

有两种不同的方法可以用来给 ArrayList 添加范围。它们是 AddRange 方法和 InsertRange 方法。AddRange 方法会把对象的范围添加到 ArrayList 的末尾处,而 InsertRange 方法则会把范围添加到 ArrayList 内指定的位置上。

static void Main(string[] args)
        {
            ArrayList nums = new ArrayList();
            nums.Add(1);
            nums.Add(2);
            nums.Add(3);
            nums.Add(4);
            nums.Add(5);
            nums.Add(6);
            nums.Add(7);
            Console.WriteLine("The original list of names: ");
            foreach (Object num in nums)
                Console.WriteLine(num);
            Console.WriteLine();
            int[] newNums = new int[] { -1, 0 };
            ArrayList moreNums = new ArrayList();
            moreNums.Add(8);
            moreNums.Add(9);
            moreNums.Add(10);
            moreNums.Add(11);
            moreNums.Add(12);
            nums.InsertRange(0, newNums);
            nums.AddRange(moreNums);
            Console.WriteLine("The new list of names: ");
            foreach (Object num in nums)
                Console.WriteLine(num);
        }

因为指定的索引为 0,所以是在 ArrayList 开始处添加了。而后面的几个名字由于使用了 AddRange方法而被添加到了末尾处。

许多程序员还找到了另外两种非常有用的方法ToArray方法和GetRange方法。GetRange方法会返回来自ArrayList的对象的范围作为另外一个 ArrayList。而 ToArray 方法则会把 ArrayList 的所有元素复制给一个数组。首先来看一看GetRange 方法。

GetRange 方法会取走两个参数:起始索引以及要从 ArrayList 找回的元素数量。GetRange 方法没有破坏性,因为这只是把对象从原始 ArrayList 复制给新的 ArrayList。

ToArray 方法允许把 ArrayList 的内容轻松传递给一个标准数组。采用 ToArray 方法的主要原因就是由于用户需要更快的数组存取访问速度。

   ArrayList someNums = new ArrayList();
            someNums = nums.GetRange(0, 2);
            Console.WriteLine("The Cope list of names: ");
            foreach (Object num in someNums)
                Console.WriteLine(num);
            object[] objArr = new object[1024];
            objArr = nums.ToArray();
            Console.WriteLine("The obj list of objArr: ");
            foreach (Object obj in objArr)
                Console.WriteLine(obj);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值