The linked list is one of the foundation concepts of programming and it's supported directly by VB.NET language elements. For example, you can read The Useful Generic List in VB.NET to learn more about one of the higher level ways to uses lists in VB.NET. But you can code a list "the hard way" too. This article shows one way to do that for a double linked list. But unlike other articles you might see, we're going to approach the solution with a lot of explanation because understanding this example is a great way to make sure you understand what's really happening in your code. The Linked List A linked list is simply an array of structures where each element contains a "pointer" to the next one. This basic structure underlies many of the collections and arrays in most programming languages - in concept at least. (The actual code that Microsoft uses ... well ... ) And in many languages such as C++, it continues to be implemented in code. In any case, understanding how one works genuinely qualifies as a fundamental concept. The simplest linked list is a single linked list. Here's a logical diagram of one: -------Click Here to display the illustration -------The arrows are the "pointer" values, that is "links", and they're addresses of some type. A language like C++ will give you direct access to memory addresses that you can use in your code that are called pointers. In Visual Basic, pointers are handled for you. (In VB.NET, you can use a Delegate and the AddressOf function which is the equivelent to a pointer in C++ more or less.) You can learn about Delegate in the article, Using Delegates in Visual Basic .NET for Runtime Flexibility. The node value is the information "payload" in the list. Note that these nodes don't have to be kept together in memory. Since a node always points to the next one, you can move them around and change the links to modify the list. For example, the links let you insert or remove individual nodes by simply changing where the links point.
If the last node points to the first one, then it's called a circular linked list. And if each node has a pointer to both the next node and the previous node, then it's called a double linked list. The Double Linked List
This is the most complex linked list, but it has the advantage that you can directly add or delete nodes with only the address of that node. A double linked list also gives you sequential access to the list in both directions. Here's a logical diagram of a double linked list. -------Click Here to display the illustration -------Since VB.NET doesn't support memory pointers directly, one way to accomplish something similar is illustrated in the (somewhat dated now) book Visual Basic Design Patterns in the chapter on interface and abstract classes. The authors provide this code to accomplish the job. (This version has been cleaned up just a bit to make it easier to understand, and I also added a property to hold one data item, ElementContent.) Public Class theElement Inherits AbstractDoubleLink Public Property ElementContent As Integer End Class Public Interface IDoubleLink Property PreviousElement As IDoubleLink Property NextElement As IDoubleLink End Interface Public MustInherit Class AbstractDoubleLink Implements IDoubleLink Private _PreviousElement As IDoubleLink Private _NextElement As IDoubleLink Public Property PreviousElement As IDoubleLink _ Implements IDoubleLink.PreviousElement Get Return _PreviousElement End Get Set(value As IDoubleLink) _PreviousElement = value End Set End Property Public Property NextElement As IDoubleLink _ Implements IDoubleLink.NextElement Get Return _NextElement End Get Set(value As IDoubleLink) _NextElement = value End Set End Property End Class
When I looked at this code, I said to myself, "Gee! I'll just whip out some code to use this class." It turned out to be easier said than done. I hate it when that happens! It would have been nice if the authors had included a more complete sample. (You can see more sample code in the article The Abstract Base Class.)
This is a really interesting piece of code. Notice that the properties of the Interface IDoubleLink are themselves IDoubleLink types. This allows a sort of recursive data structure that is easier to code than you might think: Dim thisElement As New theElement thisElement.NextElement = thisElement
-------Click Here to display the illustration -------I did it a couple of times by mistake while writing the example code to use theElement. Although code like this ... thisElement.NextElement.PreviousElement = thisElement
... turned out to have some real debugging headaches, the eventual code that accomplishes a double linked list looks like this: Dim theList As New ArrayList Private Sub Form1_Load( sender As System.Object, e As System.EventArgs ) Handles MyBase.Load ' Starting the List Dim thisElement As New theElement theList.Add(thisElement) End Sub Private Sub btnAddLink_Click( sender As System.Object, e As System.EventArgs ) Handles btnAddLink.Click ' Adding to the List Dim thisElement As New theElement thisElement.NextElement = theList(CInt(txtInsertAt.Text)).NextElement thisElement.PreviousElement = theList(CInt(txtInsertAt.Text)) thisElement.ElementContent = theList.Count theList.Add(thisElement) theList(CInt(txtInsertAt.Text)).NextElement = thisElement If thisElement.NextElement IsNot Nothing Then _ thisElement.NextElement.PreviousElement = thisElement txtInsertAt.Text = CStr(thisElement.ElementContent) End Sub Private Sub btnDelLink_Click( sender As System.Object, e As System.EventArgs ) Handles btnDelLink.Click ' Deleting from the List If theList(CInt(txtInsertAt.Text)).PreviousElement IsNot Nothing Then theList(CInt(txtInsertAt.Text)).PreviousElement.NextElement = theList(CInt(txtInsertAt.Text)).NextElement
End If If theList(CInt(txtInsertAt.Text)).NextElement IsNot Nothing Then theList(CInt(txtInsertAt.Text)).NextElement.PreviousElement = theList(CInt(txtInsertAt.Text)).PreviousElement() End If theList.RemoveAt(CInt(txtInsertAt.Text)) txtInsertAt.Text = CStr(theList.Count - 1) End Sub
The property ElementContent is used in this code to "keep track" of which node is which. (Otherwise, it's really hard to tell because nothing in VB.NET helps tell which node is which.) That value is assigned only once when nodes are added ... thisElement.ElementContent = theList.Count
... so you know it doesn't change. If you trace through the code a few times while you add and delete nodes, you will see that the relative location of the nodes (in theList) jumps all over the place, but the double links keep track of where the previous and next nodes are. And, I wrote this myself for this article ... so there could be bugs! If you find any, please let me know! Enjoy!