CSDN博客

img Latitude

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

发表于2003/6/15 14:38:00  1231人阅读

分类: 数据结构

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

                           韩睿  ( 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/
0 0

相关博文

我的热门文章

img
取 消
img