1、定義自己的MyLinkedListNode類(基本照抄了源碼)
namespace DataStructure
{
public class MyLinkedListNode<T>
{
internal MyLinkedList<T> list;
internal MyLinkedListNode<T> next;
internal MyLinkedListNode<T> prev;
internal T item;
public MyLinkedListNode(T value)
{
this.item = value;
}
internal MyLinkedListNode(MyLinkedList<T> list, T value)
{
this.list = list;
this.item = value;
}
public MyLinkedList<T> List
{
get { return this.list; }
}
public MyLinkedListNode<T> Next
{
get
{
if (this.next != null && this.next != this.list.head)
return this.next;
return null;
}
}
public MyLinkedListNode<T> Previous
{
get
{
if (this.prev != null && this != this.list.head)
return this.prev;
return null;
}
}
public T Value
{
get { return this.item; }
set { this.item = value; }
}
internal void Invalidate()
{
this.list = null;
this.next = null;
this.prev = null;
}
}
}
2、定義自己的MyLinkedList類(大部分照抄了源碼)
using System;
namespace DataStructure
{
public class MyLinkedList<T>
{
internal MyLinkedListNode<T> head;
internal int count;
public int Count
{
get { return this.count; }
}
public MyLinkedListNode<T> First
{
get { return this.head; }
}
public MyLinkedListNode<T> Last
{
get
{
if (this.head != null)
return this.head.prev;
return (MyLinkedListNode<T>) null;
}
}
public MyLinkedListNode<T> AddAfter(MyLinkedListNode<T> node, T value)
{
this.ValidateNode(node);
MyLinkedListNode<T> newNode = new MyLinkedListNode<T>(node.list, value);
this.InternalInsertNodeBefore(node.next, newNode);
return newNode;
}
public void AddAfter(MyLinkedListNode<T> node, MyLinkedListNode<T> newNode)
{
this.ValidateNode(node);
this.ValidateNewNode(newNode);
this.InternalInsertNodeBefore(node.next, newNode);
newNode.list = this;
}
public MyLinkedListNode<T> AddBefore(MyLinkedListNode<T> node, T value)
{
this.ValidateNode(node);
MyLinkedListNode<T> newNode = new MyLinkedListNode<T>(node.list, value);
this.InternalInsertNodeBefore(node, newNode);
if (node == this.head)
this.head = newNode;
return newNode;
}
public void AddBefore(MyLinkedListNode<T> node, MyLinkedListNode<T> newNode)
{
this.ValidateNode(node);
this.ValidateNewNode(newNode);
this.InternalInsertNodeBefore(node, newNode);
newNode.list = this;
if (node != this.head)
return;
this.head = newNode;
}
public MyLinkedListNode<T> AddFirst(T value)
{
MyLinkedListNode<T> newNode = new MyLinkedListNode<T>(this, value);
if (this.head == null)
{
this.InternalInsertNodeToEmptyList(newNode);
}
else
{
this.InternalInsertNodeBefore(this.head, newNode);
this.head = newNode;
}
return newNode;
}
public void AddFirst(MyLinkedListNode<T> node)
{
this.ValidateNewNode(node);
if (this.head == null)
{
this.InternalInsertNodeToEmptyList(node);
}
else
{
this.InternalInsertNodeBefore(this.head, node);
this.head = node;
}
node.list = this;
}
public MyLinkedListNode<T> AddLast(T value)
{
MyLinkedListNode<T> newNode = new MyLinkedListNode<T>(this, value);
if (this.head == null)
this.InternalInsertNodeToEmptyList(newNode);
else
this.InternalInsertNodeBefore(this.head, newNode);
return newNode;
}
public void AddLast(MyLinkedListNode<T> node)
{
this.ValidateNewNode(node);
if (this.head == null)
this.InternalInsertNodeToEmptyList(node);
else
this.InternalInsertNodeBefore(this.head, node);
node.list = this;
}
public void Clear()
{
MyLinkedListNode<T> linkedListNode1 = this.head;
while (linkedListNode1 != null)
{
MyLinkedListNode<T> linkedListNode2 = linkedListNode1;
linkedListNode1 = linkedListNode1.Next;
linkedListNode2.Invalidate();
}
this.head = null;
this.count = 0;
}
public bool Contains(T value)
{
return this.Find(value) != null;
}
public MyLinkedListNode<T> Find(T value)
{
MyLinkedListNode<T> linkedListNode = this.head;
if (linkedListNode != null)
{
while (!linkedListNode.item.Equals(value))
{
linkedListNode = linkedListNode.next;
if (linkedListNode == this.head)
{
return null;
}
}
return linkedListNode;
}
return null;
}
public bool Remove(T value)
{
MyLinkedListNode<T> node = this.Find(value);
if (node == null)
return false;
this.InternalRemoveNode(node);
return true;
}
public void Remove(MyLinkedListNode<T> node)
{
this.ValidateNode(node);
this.InternalRemoveNode(node);
}
private void InternalInsertNodeBefore(MyLinkedListNode<T> node, MyLinkedListNode<T> newNode)
{
newNode.next = node;
newNode.prev = node.prev;
node.prev.next = newNode;
node.prev = newNode;
++this.count;
}
private void InternalInsertNodeToEmptyList(MyLinkedListNode<T> newNode)
{
newNode.next = newNode;
newNode.prev = newNode;
this.head = newNode;
++this.count;
}
internal void InternalRemoveNode(MyLinkedListNode<T> node)
{
if (node.next == node)
{
this.head = null;
}
else
{
node.next.prev = node.prev;
node.prev.next = node.next;
if (this.head == node)
this.head = node.next;
}
node.Invalidate();
--this.count;
}
internal void ValidateNode(MyLinkedListNode<T> node)
{
if (node == null)
throw new Exception("MyLinkedListNode爲null");
if (node.list != this)
throw new Exception("node所在的MyLinkedList不是這個");
}
internal void ValidateNewNode(MyLinkedListNode<T> node)
{
if (node == null)
throw new Exception("MyLinkedListNode爲null");
if (node.list != null)
throw new Exception("node所在的MyLinkedList不是這個");
}
public override string ToString()
{
MyLinkedListNode<T> linkedListNode = this.head;
if (linkedListNode != null)
{
string str="";
do
{
str += " " + linkedListNode.item;
linkedListNode = linkedListNode.next;
} while (linkedListNode != this.head);
return str;
}
return null;
}
}
}
注意:參考代碼可以得知,C#中的LinkedList內部是一個雙向循環鏈表。LinkedListNode在內部相互連接形成了一個雙向環。在LinkedList中只是指定了head,沒有去指定last。而查找Last時只需通過head.prev就可以得到。而我們在外部使用時使用的是Next會去判斷內部的next是否爲head,如果是就返回null。外部使用的Previous會去判斷當前節點是不是head,如果是就返回null。這樣在外部訪問時頭尾的鏈接就斷開了。(仔細閱讀源碼就能構很好的理解雙向循環鏈表以及它的優點了)