Linked Lists 


Introduction Inserting Nodes
Pointers Deleting Nodes
Creating Lists Destroying Lists
Printing Lists Warning

Sample Program


Introduction

One of the dynamic data structures than can be constructed is the linked list. A linked list can be pictured as a collection of elements or nodes, each containing some data as well as a link, or pointer, to the next node in the list. 

Each node in the linked list must contain at least two fields. The first is the data field. It can be a simple integer, a character, a string or even a large structure or object containing many fields. This will be referred to here as the Info field. The second field is the pointer, or link, to the next node in the list. This will be referred to as the nextNode field.

Pointers

Recall that an object reference, or pointer, contains the address in memory of an object.  In most machines this is an integer value, since memory locations have integer addresses.  However, an object reference cannot be assigned an integer value.  

Pointers are important for creating dynamic data structures such as linked lists, since they provide a way of linking each component to the next component in the structure.  Because the only types of pointers that Visual Basic provides are references to objects, a linked list in VB must use objects for its nodes.

The "node class" should include a nextNode variable that indicates the next node in the list. It should also include variables to hold whatever data the program needs to manipulate.  These variables should be declared Private within the class.  Sample code for the linkNode class follows:


  '-------------------------------------------------------------------------------------------------------------------   
   ' linkNode class
  '-------------------------------------------------------------------------------------------------------------------   

   ' instance variables

   Private info As Integer
   Private nextNode As linkNode

   ' class methods

  '-------------------------------------------------------------------------------------------------------------------
   ' Constructor
  '-------------------------------------------------------------------------------------------------------------------
   Private Sub Class_Initialize( )
      nextNode = Nothing
   End Sub

  '-------------------------------------------------------------------------------------------------------------------
   ' Set node value
  '-------------------------------------------------------------------------------------------------------------------
   Public Sub setInfo(ByVal newValue As Integer)
      info = newValue
   End Sub

  '-------------------------------------------------------------------------------------------------------------------
   ' Return node value
  '-------------------------------------------------------------------------------------------------------------------
   Public Function getInfo( ) As Integer
      getInfo = info
   End Function

  '-------------------------------------------------------------------------------------------------------------------
   ' Reset nextNode reference
  '-------------------------------------------------------------------------------------------------------------------
   Public Sub setNextNode(ByRef followingNode As linkNode)   
      nextNode = followingNode
   End Sub

  '-------------------------------------------------------------------------------------------------------------------
   ' Return nextNode reference
  '-------------------------------------------------------------------------------------------------------------------
   Public Function getNextNode( ) As linkNode
      getNextNode = nextNode
   End Function



Because each node is an object, the New statement must be used to create new nodes. It assigns their variable values and uses their nextNode references to connect them.

An external pointer to the list is also needed so that the program can access the entire list. Nodes in a linked list are not accessed directly or randomly. Instead, the first node is accessed through the external pointer, the second node through the first node's pointer, the third node through the second node's pointer, etc., to the end of the list. To indicate where the list ends, the nextNode element of the last node can be set to Nothing.


Creating A Linked List

The following code sample demonstrates how to create a linked list of four nodes of type ListNode, all linked together.  For the sake of the example, one of the data components of each node has been set to store the loop control variable.


   Const numNodes As Integer = 4   

   Dim List As linkNode
   Dim Ptr1 As linkNode
   Dim Ptr2 As linkNode
   Dim lcv As Integer

   For lcv = 1 To numNodes
      Ptr2 = New linkNode
      Ptr2.setInfo(lcv)
      If lcv = 1 Then
         Ptr1 = Ptr2
         List = Ptr2
      Else
         Ptr1.setNextNode(Ptr2)
         Ptr1 = Ptr2
      End If
   Next lcv

   Ptr1.setNextNode(Nothing)

      Ptr2 = New linkNode
      Ptr2.setInfo (lcv)        
result in:

 

     If lcv = 1 Then
            Ptr1 = Ptr2
            List = Ptr2                
result in:

In the next iteration of the loop....

      Ptr2 = New linktNode
      Ptr2.setInfo (lcv)        
result in:

      

      Else
            Ptr1.setNextNode(Ptr2)
results in: 

      

            Ptr1 = Ptr2                    results in: 

       

Eventually the code results in:

     

Notice that the value Nothing is assigned to the last pointer in the list. Nothing is indicated graphically by placing a slash (\) across the field whose value is Nothing. When traversing the list, the program can compare the link field of each component in the list to Nothing to see when the end of the list has been reached.

As linked lists become more familiar, they will be created by the insertion of nodes one at a time as they are needed by calling the appropriate insertion procedure. 

 


Printing A Linked List

To print the elements in a linked list, the value of the first element is printed, then the second, then the third and so on until the end of the list is reached. This algorithm involves a simple loop to traverse the list, using a temporary pointer to point to each successive node. The temporary pointer, Ptr, is first initialized to the beginning of the list with the statement

Ptr = List

To print the value of the node pointed to by Ptr


Print Ptr.getInfo ( )      ' replace getInfo  with the correct accessor method

and to move Ptr to the next node

Ptr = Ptr.getNextNode( )

This process is repeated until the end of the loop is reached. This is indicated when the pointer variable is Nothing.

While Not Ptr Is Nothing

The entire procedure to print all the values in the linked list might look like the following.  Note that this sub, as well as all following subs, are included in a class called clsLinkedList that has a single instance variable, List, of type linkNode.


   '-------------------------------------------------------------------------------------------------------------------   
   ' Cycle through a linked list, printing the   
   ' value of each node
   '-------------------------------------------------------------------------------------------------------------------

   Public Sub printList( )
      Dim Ptr As linkNode
      Ptr = List
      While Not Ptr Is Nothing
         Debug.Print (Ptr.getInfo( ))
         Ptr = Ptr.getNextNode( )
      Wend
   End Sub

 


Inserting Into A Linked List

A procedure for inserting a node into a linked list must have two parameters: a linked list and the element to be inserted. There are two ways of inserting -- either inserting an element as the first element in the list or inserting an element into its proper place depending on the order of the list elements.


Inserting as the first element ....

To insert an element as the first one in an existing linked list requires two steps: create the element and insert it at the beginning of the list. The program must first create the element set its pointer to the first element in the list, and then set the list pointer to point to the new element. (Note that before calling pushNode the first time (i.e., if the List has no elements), List should be initialized to Nothing.)

 


   '-------------------------------------------------------------------------------------------------------------------   
  
' Add a new node to the beginning of a linked list
   '-------------------------------------------------------------------------------------------------------------------   
  
Public Sub pushNode(ByVal nodeValue As Integer)
      Dim newNode As New linkNode ' create new node
   
      newNode.setInfo(nodeValue) ' set value of new node
      newNode.setNextNode(List)   ' make nextNode point to start of List
      List = newNode                            ' reset List to newNode
   End Sub

 

       Dim newNode As New ListNode ' create new node

       newNode.setInfo (nodeValue)      ' set value of new node

       newNode.setNextNode(List)      ' make nextNode point to start of List

       List = newNode                          ' reset List to newNode

 

 Click for animation 

 

Compare this to the code that would be needed to add a new item to the beginning of an array.  In an array, every entry would have to be moved one space to make room for the new item.  If the array is long, the insertion operation could take a long time.  With a linked list, an insertion can be accomplished in just two steps.


The following algorithm is more versatile.  Instead of merely inserting an item at the beginning of a list, it accepts a value and places it in its proper position, regardless of whether that position is at the beginning, middle, or end of a linked list.  



Inserting In the Proper Position ....

To insert an element in the proper place in a sorted list requires that the proper position in the list be determined. This requires looping through all the nodes until a node with a greater Info field is found.

     Ptr = List
     While Ptr.getInfo( ) < nodeValue
            Ptr = Ptr.nextNode

If the node referenced by Ptr is the one whose value is greater than the one to be inserted, then the new element should be inserted before that node. In other words, the pointer has passed the position where the new element should be inserted. Since the program needs to know the previous node in the list so that it can change its pointer field to point to the new element, the insertion algorithm must maintain an additional pointer, Back, to keep track of the previous node.

     Ptr = List
     While Ptr.getInfo( ) < nodeValue
            Back = Ptr
            Ptr = Ptr.nextNode
      Wend


This algorithm is sufficient for handling the insertion of elements at the front of the list or inside the list, but it requires modification before it can handle elements that need to be added at the end of the list.

The algorithm contains the statement

While Ptr.getInfo( ) < nodeValue

If the element to be inserted is greater than any element in the list, which will require an insertion at the end of the list, the loop does not end before Ptr is set to Nothing. The loop then tries to access Ptr.nextNode when Ptr has been set to Nothing, which results in an error message. Therefore the loop needs to have two conditions -- it must be executed while Not Ptr Is Nothing and while Ptr.GetInfo is less than the element to be inserted. However, the code

While (Not Ptr Is Nothing) And  (Ptr.getInfo( ) < nodeValue)

does not work, because VB evaluates both sides of the expression, even if the first evaluates to false. The situation remains the same -- even after Ptr is set to Nothing, the compiler attempts to evaluate Ptr.getInfo, resulting in an error condition.

A Boolean variable provides a solution. It will be initialized to False and changed to True when the insertion point is found.

While (Not Ptr Is Nothing) And Not Found

This takes care of all three cases: the insertion at the front, the middle, and the end. The following procedure represents a general insertion algorithm.


  '-------------------------------------------------------------------------------------------------------------------
  ' Given a value to insert in a linked list, place
  ' it in a new node, and pass the node to insertNode
  '-------------------------------------------------------------------------------------------------------------------
   Public Sub insertValue(ByVal nodeValue As Integer)
      Dim newNode As New linkNode
      newNode.setInfo(nodeValue)
      insertNode(newNode)
   End Sub 

  '-------------------------------------------------------------------------------------------------------------------
  
' Given a node to insert in a linked list, locate the proper position,
   ' and insert it into the list.
   '-------------------------------------------------------------------------------------------------------------------
  
Public Sub insertNode(ByVal P As linkNode)

      Dim Found As Boolean
      Dim Ptr As linkNode
      Dim Back As linkNode

      Back = Nothing
      Ptr = List
      Found = False

      While (Not Ptr Is Nothing) And Not Found
         If Ptr.getInfo( ) > nodeValue Then
            Found = True
         Else
            Back = Ptr
            Ptr = Ptr.getNextNode( )
         End If
      Wend
      P.setNextNode(Ptr)
      If Back Is Nothing Then ' if True the node must be the first
         List = P ' insert as first element
      Else
         Back.setNextNode(P)
      End If
   End Sub


Insertion at beginning:

Goal: Insert 3 into the list. First the procedure gets a new node, P, and puts 3 in the Info field. The Back pointer is set to Nothing, the loop pointer Ptr is set to List, and Found is set to False.

 

Since Ptr is not Nothing and Found is False, the While loop is executed. Ptr.getInfo( ) is greater than nodeValue (5 > 3), so Found is set to True. The While loop is terminated. P.nextNode is set to Ptr. Back is Nothing (indicating that the new element will be the first), so List is set to P.


Insertion in the middle:

Goal: Insert 6 into the list. The initialization is the same as abov
e

The expression in the If statement (Ptr.getInfo ( ) > nodeValue) is False (3 < 4), so Back is set to Ptr and Ptr is advanced to Ptr.nextNode. The While loop is executed again and now the expression in the If statement (5 > 4) is True, so Found is set to True.

The While loop is not executed since Found is now True. P.nextNode is set to Ptr. 

Back is not Nothing so Back.nextNode is set to P.

The final results of the insertion appear below.

 

 Click for animation 

 


Insertion at the end.

Goal: Insert 9 into the list.  The initialization is the same as above.

The expression in the If statement (Ptr.getInfo ( ) > nodeValue) is False (5 < 9), so Back is set to Ptr and Ptr is advanced to Ptr.nextNode. 

The While loop is executed again and still the expression in the If statement (Ptr.getInfo ( ) > nodeValue) is False (7 < 9), so Back is set to Ptr and Ptr is advanced to Ptr.nextNode, which is Nothing.

The While loop is not executed because the condition (Not Ptr Is Nothing) is False . P.nextNode is set to Ptr (Nothing in this case) and Back.nextNode is set to P.

The final results of the insertion appear below.

 

 Click for animation

 


Deleting From A Linked List

There are two types of deletions: deleting the first node or deleting a node with a specified Info field.

To delete the first node, the program sets the List pointer to the second node, sets the first node's nextNode link to Nothing, and removes the reference to the first node so that it will be disposed of. The code for this procedure follows:


   '-------------------------------------------------------------------------------------------------------------------   
   ' Delete the node at the beginning of a linked list
   '-------------------------------------------------------------------------------------------------------------------   
 
  Private Sub removeFirstNode( )  
       Dim P As linkNode

  
     If Not List Is Nothing Then
          P = List
          List = List.getNextNode( )
          P.setNextNode(Nothing)     ' not essential
          P = Nothing
      End If
   End Sub

 

Deleting the First Node in a List

     P = List

List = List.getNextNode( )

P.setNextNode(Nothing)

P = Nothing

The resulting list, after garbage collection takes place, is shown below:

 

 Click here for animation 

 


The following algorithm is more versatile.  Instead of merely deleting the node at the beginning of a list, it accepts a value and locates the node with that value, and deletes it regardless of whether it is located at the beginning, middle, or end of a linked list.  


Deleting a Node with a Specified Value

To delete a node whose Info field has a certain value requires that the list be searched until a node with the same value is found.


   '---------------------------------------------------------------------------------------------------------------------   
   ' Locate the node that contains the specified
   ' value and remove it from the list
   '---------------------------------------------------------------------------------------------------------------------   
   Public Sub deleteNode(ByVal targetNode As Integer)
      Dim P As linkNode
      Dim Ptr As linkNode
      Dim Back As linkNode
      Dim Found As Boolean

      Ptr = List
      Back = Nothing
      Found = False

      While (Not Ptr Is Nothing) And Not Found
         If Ptr.getInfo( ) = targetNode Then
            Found = True
         Else
            Back = Ptr
            Ptr = Ptr.getNextNode( )
         End If
      Wend

      If Found Then
         If Back Is Nothing Then
            List = List.getNextNode( )
         Else
            Back.setNextNode(Ptr.getNextNode( ))
         End If

         Ptr.setNextNode(Nothing) ' not essential
         Ptr = Nothing
      Else
         Debug.Print ("Value " & targetNode & " not found in the linked list")
      End If
   End Sub

The process of removing the node containing 7 follows:

     Ptr = List
     Back = Nothing

 

     While (Not Ptr Is Nothing) And Not Found
        If Ptr.getInfo( ) = targetNode Then
            Found = True
         Else
            Back = Ptr

    

 

     While Ptr.getInfo( ) <> targetNode
             :
         
Ptr = Ptr.getNextNode( )

         If Back Is Nothing Then
            List = List.getNextNode( )
         Else
            Back.setNextNode(Ptr.getNextNode( ))
         End If


    
Ptr.setNextNode(Nothing)
     Ptr = Nothing

The resulting list, after garbage collection takes place, is shown below:

 

 Click here for animation

 


Destroying A Linked List

To destroy a linked list, set the List pointer to Nothing.

When the List reference is set to Nothing, the reference count of the first node in the list is reduced to zero, so the garbage collector reclaims that node.  As it destroys the first node, the system detects that the node contains a reference to another node in the nextNode variable.  Because the first node is being destroyed, the reference count of the second node is also reduced.  That makes the reference count for the second object in the list also zero, so the system reclaims it as well. This process continues in a chain reaction until every node in the list has been reclaimed by the system. As long as the program does not contain other references to objects in the list, the entire linked list can be destroyed with a single statement: List = Nothing       


 

 Click here for animation 

 


Warning

Given:

The statement P = Q yields:

Now both P and Q refer to the same object that contains 9.  The node containing 7 still exists, but P no longer refers to it.  In fact, unless there is another reference to the node, then that node is lost forever.  While it will remain in memory until it is reclaimed by the garbage collector, but there is no path to reach it.


Sample Linked Lists Program

 


  '-------------------------------------------------------------------------------------------------------------------   
  ' Linked List test routine
  '-------------------------------------------------------------------------------------------------------------------   
   Private Sub Form_Load( )

      Dim List As New clsLinkedList

      List.pushNode(99)
      List.insertValue(1)
      List.
insertValue(8)
      List.
insertValue(3)
      List.
insertValue(5)
      List.
insertValue(2)
      List.printList( )

      List.removeFirstNode( )
      List.deleteNode(1)
      List.printList( )
   End Sub

 

   ' clsLinkedList
   '------------------------------------------------------------------------------------------------------------------- 

   ' instance variables

   Private List As New linkNode

   ' class methods

   '------------------------------------------------------------------------------------------------------------------- 
  
' Add a new node to the beginning of a linked list
   '-------------------------------------------------------------------------------------------------------------------  
  
Public Sub pushNode(ByVal nodeValue As Integer)
      Dim newNode As New linkNode ' create new node
   
      newNode.setInfo(nodeValue) ' set value of new node
      newNode.setNextNode(List)   ' make nextNode point to start of List
      List = newNode ' reset List to newNode
   End Sub

  '-------------------------------------------------------------------------------------------------------------------
  ' Given a value to insert in a linked list, place
  ' it in a new node, and pass the node to insertNode
  '-------------------------------------------------------------------------------------------------------------------
   Public Sub insertValue(ByVal nodeValue As Integer)
      Dim newNode As New linkNode
      newNode.setInfo(nodeValue)
      insertNode(newNode)
   End Sub 

  '-------------------------------------------------------------------------------------------------------------------
  
' Given a node to insert in a linked list, locate the proper position,
   ' and insert it into the list.
   '-------------------------------------------------------------------------------------------------------------------
  
Public Sub insertNode(ByVal P As linkNode)

      Dim Found As Boolean
      Dim Ptr As linkNode
      Dim Back As linkNode

      Back = Nothing
      Ptr = List
      Found = False

      While (Not Ptr Is Nothing) And Not Found
         If Ptr.getInfo( ) > nodeValue Then
            Found = True
         Else
            Back = Ptr
            Ptr = Ptr.getNextNode( )
         End If
      Wend
      P.setNextNode(Ptr)
      If Back Is Nothing Then ' if True the node must be the first
         List = P ' insert as first element
      Else
         Back.setNextNode(P)
      End If
   End Sub

   '------------------------------------------------------------------------------------------------------------------- 
   ' Delete the node at the beginning of a linked list
   '-------------------------------------------------------------------------------------------------------------------
 
  Private Sub removeFirstNode( )  
       Dim P As linkNode

  
     If Not List Is Nothing Then
          P = List
          List = List.getNextNode( )
          P.setNextNode(Nothing)     ' not essential
          P = Nothing
      End If
   End Sub

   '------------------------------------------------------------------------------------------------------------------- 
   ' Locate the node that contains the specified
   ' value and remove it from the list
   '------------------------------------------------------------------------------------------------------------------- 
   Public Sub deleteNode(ByVal targetNode As Integer)
      Dim P As linkNode
      Dim Ptr As linkNode
      Dim Back As linkNode
      Dim Found As Boolean

      Ptr = List
      Back = Nothing
      Found = False

      While (Not Ptr Is Nothing) And Not Found
         If Ptr.getInfo( ) = targetNode Then
            Found = True
         Else
            Back = Ptr
            Ptr = Ptr.getNextNode( )
         End If
      Wend

      If Found Then
         If Back Is Nothing Then
            List = List.getNextNode( )
         Else
            Back.setNextNode(Ptr.getNextNode( ))
         End If

         Ptr.setNextNode(Nothing) ' not essential
         Ptr = Nothing
      Else
         Debug.Print ("Value " & targetNode & " not found in the linked list")
      End If
   End Sub


   '------------------------------------------------------------------------------------------------------------------- 
   ' Cycle through a linked list, printing the   
   ' value of each node
   '------------------------------------------------------------------------------------------------------------------- 

   Public Sub printList( )
      Dim Ptr As linkNode
      Ptr = List
      While Not Ptr Is Nothing
         Debug.Print (Ptr.getInfo( ))
         Ptr = Ptr.getNextNode( )
      Wend
   End Sub

 


  '-------------------------------------------------------------------------------------------------------------------   
   ' linkNode class
  '-------------------------------------------------------------------------------------------------------------------   

   ' instance variables

   Private info As Integer
   Private nextNode As linkNode

   ' class methods

  '-------------------------------------------------------------------------------------------------------------------
   ' Constructor
  '-------------------------------------------------------------------------------------------------------------------
   Private Sub Class_Initialize( )
      nextNode = Nothing
   End Sub

  '-------------------------------------------------------------------------------------------------------------------
   ' Set node value
  '-------------------------------------------------------------------------------------------------------------------
   Public Sub setInfo(ByVal newValue As Integer)
      info = newValue
   End Sub

  '-------------------------------------------------------------------------------------------------------------------
   ' Return node value
  '-------------------------------------------------------------------------------------------------------------------
   Public Function getInfo( ) As Integer
      getInfo = info
   End Function

  '-------------------------------------------------------------------------------------------------------------------
   ' Reset nextNode reference
  '-------------------------------------------------------------------------------------------------------------------
   Public Sub setNextNode(ByRef followingNode As linkNode)   
      nextNode = followingNode
   End Sub

  '-------------------------------------------------------------------------------------------------------------------
   ' Return nextNode reference
  '-------------------------------------------------------------------------------------------------------------------
   Public Function getNextNode( ) As linkNode
      getNextNode = nextNode
   End Function