User:Eriksiers/Linked List: Difference between revisions

From Rosetta Code
Content added Content deleted
(created)
 
(Fixed old lang -> syntaxhighlight error)
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
This is a [[linked list]] class for [[:Category:Visual Basic|Visual Basic]] & [[:Category:VBA|VBA]]. It should work at least as far back as VB4.
This is a [[linked list]] class for [[:Category:Visual Basic|Visual Basic]] & [[:Category:VBA|VBA]]. It should work at least as far back as VB4.


<lang vb>'This class is in the Public Domain.
<syntaxhighlight lang="vb">'This class is in the Public Domain.
Private Type Node
Private Type Node
data As Variant
data As Variant
prev As Variant
nPrv As Variant
next As Variant
nNxt As Variant
End Type
End Type


Line 58: Line 58:
listEmpty = False
listEmpty = False
curNode = 0
curNode = 0
nodes(0).prev = 0
nodes(0).nPrv = 0
nodes(0).next = 0
nodes(0).nNxt = 0
Else
Else
Dim tmp As Variant
Dim tmp As Variant
tmp = UBound(nodes) + 1
tmp = UBound(nodes) + 1
ReDim Preserve nodes(tmp)
ReDim Preserve nodes(tmp)
'this If splices the new node into the list
'this If block splices the new node into the list
If Before = where Then
If Before = where Then
nodes(nodes(curNode).next).prev = tmp
nodes(nodes(curNode).nNxt).nPrv = tmp
nodes(tmp).next = nodes(curNode).next
nodes(tmp).nNxt = nodes(curNode).nNxt
nodes(tmp).prev = curNode
nodes(tmp).nPrv = curNode
nodes(curNode).next = tmp
nodes(curNode).nNxt = tmp
Else
Else
nodes(nodes(curNode).prev).next = tmp
nodes(nodes(curNode).nPrv).nNxt = tmp
nodes(tmp).next = curNode
nodes(tmp).nNxt = curNode
nodes(tmp).prev = nodes(curNode).prev
nodes(tmp).nPrv = nodes(curNode).nPrv
nodes(curNode).prev = tmp
nodes(curNode).nPrv = tmp
End If
End If
curNode = tmp
curNode = tmp
Line 89: Line 89:
If UBound(nodes) > 0 Then
If UBound(nodes) > 0 Then
'patch the surrounding elements together
'patch the surrounding elements together
nodes(nodes(curNode).prev).next = nodes(curNode).next
nodes(nodes(curNode).nPrv).nNxt = nodes(curNode).nNxt
nodes(nodes(curNode).next).prev = nodes(curNode).prev
nodes(nodes(curNode).nNxt).nPrv = nodes(curNode).nPrv
'select the appropriate next item
'select the appropriate nNxt item
curNode = nodes(curNode).next
curNode = nodes(curNode).nNxt
'finally, the actual delete
'finally, the actual delete
ReDim Preserve nodes(UBound(nodes) - 1)
ReDim Preserve nodes(UBound(nodes) - 1)
Line 103: Line 103:
Else
Else
'patch the surrounding elements together
'patch the surrounding elements together
nodes(nodes(curNode).prev).next = nodes(curNode).next
nodes(nodes(curNode).nPrv).nNxt = nodes(curNode).nNxt
nodes(nodes(curNode).next).prev = nodes(curNode).prev
nodes(nodes(curNode).nNxt).nPrv = nodes(curNode).nPrv
'swap with node at end of list
'swap with node at end of list
Dim tmp As Node
Dim tmp As Node
Line 111: Line 111:
nodes(curNode) = tmp
nodes(curNode) = tmp
'patch the list
'patch the list
nodes(nodes(curNode).prev).next = curNode
nodes(nodes(curNode).nPrv).nNxt = curNode
nodes(nodes(curNode).next).prev = curNode
nodes(nodes(curNode).nNxt).nPrv = curNode
'select the appropriate next item
'select the appropriate nNxt item
If UBound(nodes) <> nodes(UBound(nodes)).next Then curNode = nodes(UBound(nodes)).next
If UBound(nodes) <> nodes(UBound(nodes)).nNxt Then curNode = nodes(UBound(nodes)).nNxt
'finally, the actual delete
'finally, the actual delete
ReDim Preserve nodes(UBound(nodes) - 1)
ReDim Preserve nodes(UBound(nodes) - 1)
Line 123: Line 123:


Public Function nextnode() As Boolean
Public Function nextnode() As Boolean
If curNode < UBound(nodes) Then
curNode = nodes(curNode).nNxt
curNode = curNode + 1
Else
curNode = 0
End If
nextnode = True
End Function
End Function


Public Function prevNode() As Boolean
Public Function prevNode() As Boolean
If curNode > 0 Then
curNode = nodes(curNode).nPrv
End Function</syntaxhighlight>
curNode = curNode - 1
Else
curNode = UBound(nodes)
End If
prevNode = True
End Function</lang>


==Simplified==
==Simplified==
Line 146: Line 136:
With minor modifications, this could conceivably work under QBasic (though obviously not as a class).
With minor modifications, this could conceivably work under QBasic (though obviously not as a class).


<lang vb>'This class is in the Public Domain.
<syntaxhighlight lang=vb>'This class is in the Public Domain.
Public Enum BeforeOrAfter
Public Enum BeforeOrAfter
Before = 0
Before = 0
Line 243: Line 233:
End If
End If
prevNode = True
prevNode = True
End Function</lang>
End Function</syntaxhighlight>

Latest revision as of 17:02, 2 January 2023

This is a linked list class for Visual Basic & VBA. It should work at least as far back as VB4.

'This class is in the Public Domain.
Private Type Node
    data As Variant
    nPrv As Variant
    nNxt As Variant
End Type

Public Enum BeforeOrAfter
    Before = 0
    After = 1
End Enum

Private nodes() As Node
Private curNode As Variant, listEmpty As Boolean

Private Sub Class_Initialize()
    listEmpty = True
    curNode = -1
End Sub

Public Property Get nodeData() As Variant
    If listEmpty Then
        Error 9
    Else
        nodeData = nodes(curNode).data
    End If
End Property

Public Property Let nodeData(ByVal vNewValue As Variant)
    If listEmpty Then
        Error 9
    Else
        nodes(curNode).data = vNewValue
    End If
End Property

Public Property Get isEmpty() As Boolean
    isEmpty = listEmpty
End Property

Public Property Get currentNode() As Variant
    currentNode = curNode
End Property

Public Property Get nodeCount() As Variant
    If listEmpty Then
        nodeCount = 0
    Else
        nodeCount = UBound(nodes) + 1
    End If
End Property

Public Function insertNode(Optional where As BeforeOrAfter, Optional data As Variant) As Boolean
    If listEmpty Then
        ReDim nodes(0)
        listEmpty = False
        curNode = 0
        nodes(0).nPrv = 0
        nodes(0).nNxt = 0
    Else
        Dim tmp As Variant
        tmp = UBound(nodes) + 1
        ReDim Preserve nodes(tmp)
        'this If block splices the new node into the list
        If Before = where Then
            nodes(nodes(curNode).nNxt).nPrv = tmp
            nodes(tmp).nNxt = nodes(curNode).nNxt
            nodes(tmp).nPrv = curNode
            nodes(curNode).nNxt = tmp
        Else
            nodes(nodes(curNode).nPrv).nNxt = tmp
            nodes(tmp).nNxt = curNode
            nodes(tmp).nPrv = nodes(curNode).nPrv
            nodes(curNode).nPrv = tmp
        End If
        curNode = tmp
    End If
    nodes(curNode).data = data
    insertNode = True
End Function

Public Function deleteNode() As Boolean
    If listEmpty Then
        Error 9
    Else
        If UBound(nodes) = curNode Then
            If UBound(nodes) > 0 Then
                'patch the surrounding elements together
                nodes(nodes(curNode).nPrv).nNxt = nodes(curNode).nNxt
                nodes(nodes(curNode).nNxt).nPrv = nodes(curNode).nPrv
                'select the appropriate nNxt item
                curNode = nodes(curNode).nNxt
                'finally, the actual delete
                ReDim Preserve nodes(UBound(nodes) - 1)
            Else
                'only item on list, so...
                ReDim nodes(0)
                listEmpty = True
                curNode = -1
            End If
        Else
            'patch the surrounding elements together
            nodes(nodes(curNode).nPrv).nNxt = nodes(curNode).nNxt
            nodes(nodes(curNode).nNxt).nPrv = nodes(curNode).nPrv
            'swap with node at end of list
            Dim tmp As Node
            tmp = nodes(UBound(nodes))
            nodes(UBound(nodes)) = nodes(curNode)
            nodes(curNode) = tmp
            'patch the list
            nodes(nodes(curNode).nPrv).nNxt = curNode
            nodes(nodes(curNode).nNxt).nPrv = curNode
            'select the appropriate nNxt item
            If UBound(nodes) <> nodes(UBound(nodes)).nNxt Then curNode = nodes(UBound(nodes)).nNxt
            'finally, the actual delete
            ReDim Preserve nodes(UBound(nodes) - 1)
        End If
        deleteNode = True
    End If
End Function

Public Function nextnode() As Boolean
    curNode = nodes(curNode).nNxt
End Function

Public Function prevNode() As Boolean
    curNode = nodes(curNode).nPrv
End Function

Simplified

This is a variation of the above class that relies on VB's array handling to keep the elements in order. It's much simpler than the above version, but will slow significantly with larger lists. (How large and how slow are largely dependent on the machine it's running on.)

With minor modifications, this could conceivably work under QBasic (though obviously not as a class).

'This class is in the Public Domain.
Public Enum BeforeOrAfter
    Before = 0
    After = 1
End Enum

Private nodes() As Variant
Private curNode As Variant, listEmpty As Boolean

Private Sub Class_Initialize()
    listEmpty = True
    curNode = -1
End Sub

Public Property Get nodeData() As Variant
    If listEmpty Then
        Error 9
    Else
        nodeData = nodes(curNode)
    End If
End Property

Public Property Let nodeData(ByVal vNewValue As Variant)
    If listEmpty Then
        Error 9
    Else
        nodes(curNode) = vNewValue
    End If
End Property

Public Property Get isEmpty() As Boolean
    isEmpty = listEmpty
End Property

Public Property Get currentNode() As Variant
    currentNode = curNode
End Property

Public Property Get nodeCount() As Variant
    If listEmpty Then
        nodeCount = 0
    Else
        nodeCount = UBound(nodes) + 1
    End If
End Property

Public Function insertNode(Optional where As BeforeOrAfter, Optional data As Variant) As Boolean
    If listEmpty Then
        ReDim nodes(0)
        listEmpty = False
        curNode = 0
    Else
        ReDim Preserve nodes(UBound(nodes) + 1)
        Dim L0 As Variant
        curNode = curNode + where
        For L0 = UBound(nodes) To curNode + 1 Step -1
            nodes(L0) = nodes(L0 - 1)
        Next
    End If
    nodes(curNode) = data
    insertNode = True
End Function

Public Function deleteNode() As Boolean
    If listEmpty Then
        Error 9
    Else
        Dim L0 As Variant
        For L0 = curNode To UBound(nodes) - 1
            nodes(L0) = nodes(L0 + 1)
        Next
        If UBound(nodes) < 1 Then
            listEmpty = True
            curNode = -1
        Else
            ReDim Preserve nodes(UBound(nodes) - 1)
        End If
        deleteNode = True
    End If
End Function

Public Function nextNode() As Boolean
    If curNode < UBound(nodes) Then
        curNode = curNode + 1
    Else
        curNode = 0
    End If
    nextNode = True
End Function

Public Function prevNode() As Boolean
    If curNode > 0 Then
        curNode = curNode - 1
    Else
        curNode = UBound(nodes)
    End If
    prevNode = True
End Function