这个链表没有暴露node接口,而是把链表本身包装成了一个Collection和List,实现了ICollection<T>, IEnumerable<T>, IList<T>接口,写的过程中参考了BCL中的实现以及Wintellect.PowerCollection的实现以及写法。并且初步通过测试。
欢迎多提意见。
namespace
FengChen.Practices
{
internal class ListNode < T >
{
public T Item; // Element item
public ListNode < T > Next;
public ListNode(T value) : this () { this .Item = value; }
internal ListNode() { this .Next = null ; }
}
public class LinkList < T > : ICollection < T > , IEnumerable < T > , IList < T >
{
private ListNode < T > m_Head;
private ListNode < T > m_End;
private Int32 m_Count;
EqualityComparer < T > m_Comparer = EqualityComparer < T > .Default;
#region ctor
public LinkList()
{
m_Head = new ListNode < T > ();
m_End = m_Head;
}
public LinkList(T[] array)
: this ()
{
if (array == null ) throw new ArgumentNullException( " array " );
foreach (T item in array) this .Add(item);
}
#endregion
#region Utility methods
public bool IsEmpty { get { return m_Head.Next == null ; } }
private ListNode < T > Find(T value, out Int32 index)
{
ListNode < T > node = m_Head.Next;
index = 0 ;
while (node != null && ! m_Comparer.Equals(value, node.Item))
{
node = node.Next;
index ++ ;
}
if (node == null ) index = - 1 ;
return node;
}
private ListNode < T > FindPrevious(T value)
{
ListNode < T > node = m_Head;
while (node.Next != null && ! m_Comparer.Equals(value, node.Next.Item))
node = node.Next;
return node;
}
#endregion
#region ICollection<T> Members
public void Add(T item) // Add the item at end
{
ListNode < T > node = new ListNode < T > (item);
m_End.Next = node;
m_End = node;
m_Count ++ ;
}
public void Clear()
{
ListNode < T > pos, temp;
pos = m_Head;
while (pos != null )
{
temp = pos.Next;
pos.Next = null ;
pos = temp;
}
m_Count = 0 ;
m_End = m_Head;
}
public bool Contains(T item)
{
Int32 i = 0 ;
return this .Find(item, out i) != null ;
}
public void CopyTo(T[] array, int index)
{
if (array == null )
throw new ArgumentNullException( " array " );
if ((index < 0 ) || (index >= array.Length))
throw new ArgumentOutOfRangeException( " index " , index, " Please check the index value! " );
if ((array.Length - index) < this .Count)
throw new ArgumentException( " Insufficient Space! " );
ListNode < T > node = m_Head.Next;
while (node != null )
{
array[index ++ ] = node.Item;
node = node.Next;
}
}
public int Count { get { return m_Count; } }
public bool IsReadOnly { get { return false ; } }
public bool Remove(T item)
{
ListNode < T > preNode = this .FindPrevious(item);
ListNode < T > tempNode = null ;
if (preNode.Next != null ) // item is found
{
if (m_End == preNode.Next) m_End = preNode;
tempNode = preNode.Next; // node to be deleted
preNode.Next = tempNode.Next;
tempNode = null ;
m_Count -- ;
return true ;
}
return false ;
}
#endregion
#region IEnumerable<T> Members
public IEnumerator < T > GetEnumerator()
{
ListNode < T > node = this .m_Head.Next;
while (node != null )
{
yield return node.Item;
node = node.Next;
}
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return this .GetEnumerator();
}
#endregion
/// <summary>
/// StreamWriter = new StreamWriter(Console.OpenStandardOutput());
/// </summary>
/// <param name="writer"></param>
public void Display(StringWriter writer)
{
// Use it like this
ListNode < T > p = m_Head.Next;
writer.Write( " The List Item is: " );
while (p != null )
{
writer.Write( " {0}--> " , p.Item);
p = p.Next;
}
writer.Write( " NULL " );
writer.Write(Environment.NewLine);
}
public override String ToString ()
{
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb);
this .Display (writer);
writer.Close ();
return sb.ToString();
}
#region IList<T> Members
public int IndexOf(T item)
{
Int32 index = 0 ;
this .Find(item, out index);
return index;
}
public void Insert( int index, T item)
{
if (index < 0 || index >= this .m_Count)
throw new ArgumentOutOfRangeException( " index " , index, " Index value is out of range, please check! " );
ListNode < T > previousNode = this .m_Head.Next;
ListNode < T > node = new ListNode < T > (item);
while ( index -- > 0 ) previousNode = previousNode.Next;
node.Next = previousNode.Next;
previousNode.Next = node;
if (m_End.Next != null ) m_End = node;
m_Count ++ ;
}
public void RemoveAt( int index)
{
if (index < 0 || index >= this .m_Count)
throw new ArgumentOutOfRangeException( " index " , index, " Index value is out of range, please check! " );
ListNode < T > previousNode = this .m_Head;
while (index -- > 0 ) previousNode = previousNode.Next;
ListNode < T > node = previousNode.Next;
if (node == null ) return ;
if (node == m_End) m_End = previousNode;
previousNode.Next = node.Next;
node.Next = null ;
node = null ;
m_Count -- ;
}
private ListNode < T > GetNode( int index)
{
if (index < 0 || index >= this .m_Count)
throw new ArgumentOutOfRangeException( " index " , index, " Index value is out of range, please check! " );
ListNode < T > node = this .m_Head.Next;
while (index -- > 0 ) node = node.Next;
return node;
}
public T this [ int index]
{
get { return this .GetNode(index).Item; }
set { this .GetNode(index).Item = value; }
}
#endregion
}
}
{
internal class ListNode < T >
{
public T Item; // Element item
public ListNode < T > Next;
public ListNode(T value) : this () { this .Item = value; }
internal ListNode() { this .Next = null ; }
}
public class LinkList < T > : ICollection < T > , IEnumerable < T > , IList < T >
{
private ListNode < T > m_Head;
private ListNode < T > m_End;
private Int32 m_Count;
EqualityComparer < T > m_Comparer = EqualityComparer < T > .Default;
#region ctor
public LinkList()
{
m_Head = new ListNode < T > ();
m_End = m_Head;
}
public LinkList(T[] array)
: this ()
{
if (array == null ) throw new ArgumentNullException( " array " );
foreach (T item in array) this .Add(item);
}
#endregion
#region Utility methods
public bool IsEmpty { get { return m_Head.Next == null ; } }
private ListNode < T > Find(T value, out Int32 index)
{
ListNode < T > node = m_Head.Next;
index = 0 ;
while (node != null && ! m_Comparer.Equals(value, node.Item))
{
node = node.Next;
index ++ ;
}
if (node == null ) index = - 1 ;
return node;
}
private ListNode < T > FindPrevious(T value)
{
ListNode < T > node = m_Head;
while (node.Next != null && ! m_Comparer.Equals(value, node.Next.Item))
node = node.Next;
return node;
}
#endregion
#region ICollection<T> Members
public void Add(T item) // Add the item at end
{
ListNode < T > node = new ListNode < T > (item);
m_End.Next = node;
m_End = node;
m_Count ++ ;
}
public void Clear()
{
ListNode < T > pos, temp;
pos = m_Head;
while (pos != null )
{
temp = pos.Next;
pos.Next = null ;
pos = temp;
}
m_Count = 0 ;
m_End = m_Head;
}
public bool Contains(T item)
{
Int32 i = 0 ;
return this .Find(item, out i) != null ;
}
public void CopyTo(T[] array, int index)
{
if (array == null )
throw new ArgumentNullException( " array " );
if ((index < 0 ) || (index >= array.Length))
throw new ArgumentOutOfRangeException( " index " , index, " Please check the index value! " );
if ((array.Length - index) < this .Count)
throw new ArgumentException( " Insufficient Space! " );
ListNode < T > node = m_Head.Next;
while (node != null )
{
array[index ++ ] = node.Item;
node = node.Next;
}
}
public int Count { get { return m_Count; } }
public bool IsReadOnly { get { return false ; } }
public bool Remove(T item)
{
ListNode < T > preNode = this .FindPrevious(item);
ListNode < T > tempNode = null ;
if (preNode.Next != null ) // item is found
{
if (m_End == preNode.Next) m_End = preNode;
tempNode = preNode.Next; // node to be deleted
preNode.Next = tempNode.Next;
tempNode = null ;
m_Count -- ;
return true ;
}
return false ;
}
#endregion
#region IEnumerable<T> Members
public IEnumerator < T > GetEnumerator()
{
ListNode < T > node = this .m_Head.Next;
while (node != null )
{
yield return node.Item;
node = node.Next;
}
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return this .GetEnumerator();
}
#endregion
/// <summary>
/// StreamWriter = new StreamWriter(Console.OpenStandardOutput());
/// </summary>
/// <param name="writer"></param>
public void Display(StringWriter writer)
{
// Use it like this
ListNode < T > p = m_Head.Next;
writer.Write( " The List Item is: " );
while (p != null )
{
writer.Write( " {0}--> " , p.Item);
p = p.Next;
}
writer.Write( " NULL " );
writer.Write(Environment.NewLine);
}
public override String ToString ()
{
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb);
this .Display (writer);
writer.Close ();
return sb.ToString();
}
#region IList<T> Members
public int IndexOf(T item)
{
Int32 index = 0 ;
this .Find(item, out index);
return index;
}
public void Insert( int index, T item)
{
if (index < 0 || index >= this .m_Count)
throw new ArgumentOutOfRangeException( " index " , index, " Index value is out of range, please check! " );
ListNode < T > previousNode = this .m_Head.Next;
ListNode < T > node = new ListNode < T > (item);
while ( index -- > 0 ) previousNode = previousNode.Next;
node.Next = previousNode.Next;
previousNode.Next = node;
if (m_End.Next != null ) m_End = node;
m_Count ++ ;
}
public void RemoveAt( int index)
{
if (index < 0 || index >= this .m_Count)
throw new ArgumentOutOfRangeException( " index " , index, " Index value is out of range, please check! " );
ListNode < T > previousNode = this .m_Head;
while (index -- > 0 ) previousNode = previousNode.Next;
ListNode < T > node = previousNode.Next;
if (node == null ) return ;
if (node == m_End) m_End = previousNode;
previousNode.Next = node.Next;
node.Next = null ;
node = null ;
m_Count -- ;
}
private ListNode < T > GetNode( int index)
{
if (index < 0 || index >= this .m_Count)
throw new ArgumentOutOfRangeException( " index " , index, " Index value is out of range, please check! " );
ListNode < T > node = this .m_Head.Next;
while (index -- > 0 ) node = node.Next;
return node;
}
public T this [ int index]
{
get { return this .GetNode(index).Item; }
set { this .GetNode(index).Item = value; }
}
#endregion
}
}
欢迎多提意见。