|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Introduction
I was writing some code in C# the other day and I realized I needed a linked list to
make something I was doing easier. I wanted a list that would collapse around a removed object,
and that was not be backed by an array. I naturally went to the .NET Framework and the That inspired me to write my own linked list. Not just a standard linked list, but a doubly-linked list. A list where each element has a reference to the next element and the previous element. A standard linked list would just have a reference to the next element. With doubly-linked list, the list can easily be traversed forward and backwards and delete an element in constant time. Break It Down
My doubly-linked list, which we will call just
Then under this public facade we have a lot of very important private members that do the bulk of the work.
Some DetailsThe The
The Node node = headerNode;
if (index < (count / 2))
{
for (int i = 0; i <= index; i++)
node = node.NextNode;
}
else
{
for (int i = count; i > index; i--)
node = node.PreviousNode;
}
The if (value != headerNode)
{
value.PreviousNode.NextNode = value.NextNode;
value.NextNode.PreviousNode = value.PreviousNode;
count--;
modifications++;
}
The
The
The private class LinkedListEnumerator : IEnumerator
{
private LinkedList linkedList;
private int validModificationCount;
private Node currentNode;
public LinkedListEnumerator(LinkedList linkedList)
{
this.linkedList = linkedList;
validModificationCount = linkedList.modifications;
currentNode = linkedList.headerNode;
}
public object Current
{
get
{
return currentNode.CurrentNode;
}
}
public void Reset()
{
currentNode = linkedList.headerNode;
}
public bool MoveNext()
{
bool moveSuccessful = false;
if (validModificationCount != linkedList.modifications)
throw new SystemException(
"A concurrent modification occured to the LinkedList " +
"while accessing it through it's enumerator.");
currentNode = currentNode.NextNode;
if (currentNode != linkedList.headerNode)
moveSuccessful = true;
return moveSuccessful;
}
}
The public virtual void InsertAll(int index, ICollection collection)
{
if (collection != null)
{
if (0 < collection.Count)
{
modifications++;
Node startingNode = (index == count ?
headerNode : FindNodeAt(index));
Node previousNode = startingNode.PreviousNode;
foreach (object obj in collection)
{
Node node = new Node(obj,
startingNode, previousNode);
previousNode.NextNode = node;
previousNode = node;
}
startingNode.PreviousNode = previousNode;
count += collection.Count;
}
else
throw new ArgumentOutOfRangeException("index",
index, "less than zero");
}
else
throw new ArgumentNullException("collection");
}
The public virtual object Clone()
{
LinkedList listClone = new LinkedList();
for (Node node = headerNode.NextNode; node != headerNode;
node = node.NextNode)
listClone.Add(node.CurrentNode);
return listClone;
}
public virtual LinkedList Clone(bool attemptDeepCopy)
{
LinkedList listClone;
if (attemptDeepCopy)
{
listClone = new LinkedList();
object currentObject;
for (Node node = headerNode.NextNode; node != headerNode;
node = node.NextNode)
{
currentObject = node.CurrentNode;
if (currentObject == null)
listClone.Add(null);
else if (currentObject is ICloneable)
listClone.Add(((ICloneable)currentObject).Clone());
else
throw new SystemException("The object of type [" +
currentObject.GetType() +
"] in the list is not an ICloneable, cannot attempt " +
"a deep copy.");
}
}
else
listClone = (LinkedList)this.Clone();
return listClone;
}
ConclusionI believe this is a great class to learn how to implement your own custom collection. It is also very useful as it is, and ready to be included in your next project. The rest of the class is fairly straight-forward for a list collection. The class is fairly well commented using XML comment tags. Experienced and intermediate developers should have no trouble following the class.
This | ||||||||||||||||||||