Henry手记—.NET数据结构对象补遗之单链表(三)

原创 2003年06月15日 14:38:00

         Henry手记—.NET数据结构对象补遗之单链表(三)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

                           韩睿  ( 06/15/2003)

3.8      Item属性

Item属性提供给VB.NETlist(2)这样的方式操作列表,也就能赋予单链表和ArrayList数组一样的索引方式,尽管在实现上效率不如数组,但这样方便的操作手段我们不能放过:

Default Public Overridable Property Item( _

                 ByVal index As Integer) As Object Implements IList.Item

        'Item属性,读写链表的索引处结点的数据值

        Get

            Validate(index)

            Return FindByIndex(index).Data

        End Get

        Set(ByVal Value As Object)

            Validate(index, Value)

            FindByIndex(index).Data = Value

        End Set

End Property

  同样的,我们还提供计数功能,利用的就是上述各种操作中都在进行更改的nodeCount成员。

Public Overridable ReadOnly Property Count() As Integer _

                                Implements IList.Count

        '返回链表元素总数

        Get

            Return nodeCount

        End Get

End Property

到这里,我们是不是已经实现了基本的链表操作功能了?但是,还有一些重要机制并没有揭示给读者朋友,让我们继续吧。

3.9      For Each循环枚举的实现

For Each是个很强大的遍历方法,要实现这个功能,链表类必须实现IEnumerable接口,在IList我们通过实现继承自IEnumerableGetEnumerator函数来达到这一目标。但该函数返回的是IEnumerator枚举器类型,因此我们要实现自己的枚举器来达到对链表的处理:

IEnumerator 是所有枚举数的基接口。枚举数只允许读取集合中的数据。枚举数无法用于修改基础集合。IEnumerator接口支持两种方法和一个属性。MoveNext方法能在集合中一次移动一条记录。Reset方法能使枚举器复位到集合的起始。Current只读属性能从集合返回当前记录。

最初,枚举数被定位于集合中第一个元素的前面。Reset 也将枚举数返回到此位置。在此位置,调用 Current 会引发异常。因此,在读取 Current 的值之前,必须调用 MoveNext 将枚举数提前到集合的第一个元素。

在调用 MoveNext Reset 之前,Current 返回同一对象。MoveNext Current 设置为下一个元素。

在传递到集合的末尾之后,枚举数放在集合中最后一个元素后面,且调用 MoveNext 会返回 false。如果最后一次调用 MoveNext 返回 false,则调用 Current 会引发异常。若要再次将 Current 设置为集合的第一个元素,可以调用 Reset,然后再调用 MoveNext

只要集合保持不变,枚举数就保持有效。如果对集合进行了更改(例如添加、修改或删除元素),则该枚举数将失效且不可恢复,并且下一次对 MoveNext Reset 的调用将引发 InvalidOperationException。如果在 MoveNext Current 之间修改集合,那么即使枚举数已经无效,Current 也将返回它所设置成的元素。现在您就会理解我们在前面不断看到的那个version的用法了。

由于我们在之前把ListNode定义为嵌套类,同时需要调用SLList类的成员,所以把自定义的实现IEnumerator接口的类置入SLList类中,成为第二个嵌套类:

Public Overridable Function GetEnumerator() As IEnumerator _

                                   Implements IList.GetEnumerator

        Return New SLListEnumerator(Me)

    End Function

下面就是实现IEnumerator接口的类了。

    Protected Class SLListEnumerator

        Implements IEnumerator

        '嵌套在SLList内部的计数器类

        Protected list As SLList

        Protected currentElement As Object

        Protected currentNode As ListNode '嵌套在内部才可以使用这个类

        Protected version As Integer '内部版本记录,用于比对链表是否已有改变

 

        Public Sub New(ByVal list As SLList)

            '初始化

            Me.list = list

            Me.version = list.version

            Me.currentElement = list

            Me.currentNode = list.head

        End Sub

 

        Protected Overridable Sub VerifyListIsUnchanged()

            '判断版本是否在枚举器创建后还发生了改变

            If Not version = list.version Then

                Throw New InvalidOperationException( _

                  "该链表在枚举器创建后发生了改变")

            End If

        End Sub

 

        Public Overridable ReadOnly Property Current() As Object _

                                    Implements IEnumerator.Current

            '返回当前记录

            Get

                '判断是否已经到了链表尾或是否调用了MoveNext查找记录

                If currentElement Is list Then

                    If currentNode Is list.head Then

                        Throw New InvalidOperationException( _

                          "Current方法在MoveNext被调用前是无效的.")

                    Else

                        Throw New InvalidOperationException( _

                          "已到达集合尾,因此Current方法无效")

                    End If

                End If

                Return currentElement

            End Get

        End Property

 

        Public Overridable Function MoveNext() As Boolean _

                           Implements IEnumerator.MoveNext

            '将枚举器继续移到下一个对象

            VerifyListIsUnchanged()

            If Not currentNode.NextNode Is Nothing Then

                currentNode = currentNode.NextNode

                currentElement = currentNode.Data

                Return True

            Else

                currentElement = list

                currentNode = list.head

                Return False

            End If

        End Function

 

        Public Overridable Sub Reset() Implements IEnumerator.Reset

            '将枚举器重置为其初始位置

            VerifyListIsUnchanged()

            currentNode = list.head

            currentElement = list

        End Sub

End Class

----

声明:本文版权与解释权归韩睿所有,如需转载,请保留完整的内容及此声明。

QQ: 18349592

E-Mail: henry7685@hotmail.com

 请访问本人专栏:http://www.csdn.net/develop/author/netauthor/Latitude/

Henry手记—.NET数据结构对象补遗之单链表(二)

             Henry手记—.NET数据结构对象补遗之单链表(二)                           韩睿  ( 06/15/2003) 3.4根据索引位置或数据元素值...
  • Latitude
  • Latitude
  • 2003年06月15日 14:37
  • 1309

Henry手记—.NET数据结构对象补遗之单链表(四)

       Henry手记—.NET数据结构对象补遗之单链表(四)                            韩睿  ( 06/15/2003)3.10      其他属性本文并没有全部...
  • Latitude
  • Latitude
  • 2003年06月15日 14:38
  • 1314

Henry手记—.NET数据结构对象补遗之单链表(一)

  Henry手记—.NET数据结构对象补遗之单链表(一)              韩睿  ( 06/15/2003) .NET Framework提供了众多常用的数据结构对象,放在System.C...
  • Latitude
  • Latitude
  • 2003年06月16日 09:27
  • 1690

数据结构之单链表(C++实现)

很早前就想用C++来实现那些常用的数据结构。 今天就算是个开端把。还是那句话,看的再多不如自己动手写一遍。 按照自己的思路写。首先你得熟悉那种结构的特点,然后才能谈实现。  链表是一种很常用的数...
  • complety
  • complety
  • 2012年04月08日 15:25
  • 7507

Java数据结构-单链表

本文将数据结构知识中重要知识点:数据元素,结点,数据类型,抽象数据类型,抽象数据类型的实现、以及对新定义的数据结构的应用等知识通过下述java代码的形式串联起来,以从宏观上对数据结构有一个透彻的理解和...
  • wk_learn
  • wk_learn
  • 2014年06月13日 08:43
  • 3379

【数据结构与算法】——链表篇

链表属于线性结构之一,主要功能是提供可动态扩展的线性结构,可使用不连续的的内存空间,为程序的动态特性提供支持。逻辑结构如下(图片引用自CSDN博客)            一般的定义如下 /*...
  • theprinceofelf
  • theprinceofelf
  • 2012年01月16日 15:49
  • 3668

数据结构之链表学习心得

顺序表从节点之间的链接方式分我连续空间顺序表和链式顺序表,前者的实现就是在普通数组上做了封装,后者实现就是前一个节点保存后一个节点的地址。本文讨论的就是后者,链式顺序表的一个最明显的特征,就是在增减,...
  • liubo2011
  • liubo2011
  • 2016年05月01日 10:02
  • 633

数据结构单链表的建立的使用

建立单链表的意义: 储存数据 一般就是用的数组,灵活性也是很好的,但是数组的大小必须在开始的时候预先定义好,在未知的情况下就很容易损耗空间; 单链表:...
  • woshinannan741
  • woshinannan741
  • 2015年10月03日 18:02
  • 2459

《数据结构》进行曲 之 单链表实现学生信息管理系统

#include #include using namespace std; #define MAX 100 typedef struct STU{ char name[20]; char s...
  • sungaochao
  • sungaochao
  • 2016年02月26日 15:03
  • 1646

2120数据结构实验之链表五:单链表的拆分

数据结构实验之链表五:单链表的拆分#include #include using namespace std; int a=0,b=0; struct node { int data; ...
  • yue_luo_
  • yue_luo_
  • 2016年10月08日 19:58
  • 104
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Henry手记—.NET数据结构对象补遗之单链表(三)
举报原因:
原因补充:

(最多只允许输入30个字)