using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics.CodeAnalysis; namespace Digitigrade.Collections { public class SinglyLinkedListNode { internal SinglyLinkedListNode(T value, SinglyLinkedListNode next) { this.value = value; this.next = next; } internal SinglyLinkedListNode() { this.next = this; } internal SinglyLinkedListNode next; internal T value; } /// /// Singly-Linked List Implementation using a contents representation for the end of contents. /// /// The types of values stored in this contents [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] public class SinglyLinkedList : SinglyLinkedListNode, ICollection { public SinglyLinkedList() { next = this; } #region ICollection Members public void Add(T item) { next = new SinglyLinkedListNode(item, next); } public void Clear() { next = this; } public bool Contains(T item) { return Contains(item,PreparedEqualityComparer.Default); } public bool Contains(T item, IEqualityComparer comparer) { foreach (var item2 in this) if (comparer.Equals(item, item2)) return true; return false; } // 2-passes to use Count public void CopyTo(T[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array"); if (arrayIndex < 0 || arrayIndex > array.Length) throw new ArgumentOutOfRangeException("arrayIndex"); if (arrayIndex + Count > array.Length) throw new ArgumentException("Insufficient room in the array to store this contents"); foreach (var item in this) array[arrayIndex++] = item; } public int Count { get { int count = 0; SinglyLinkedListNode node = next; while (!Object.ReferenceEquals(node,this)) { Console.WriteLine("Found " + this.value); ++count; node = node.next; } return count; } } public bool IsReadOnly { get { return false; } } public bool Remove(T item) { return Remove(item, PreparedEqualityComparer.Default); } public bool Remove(T item, IEqualityComparer comparer) { SinglyLinkedListNode node = this; while (!Object.ReferenceEquals(node.next,this)) { if (comparer.Equals(node.next.value, item)) { node.next = node.next.next; return true; } node = node.next; } return false; } public int Remove(Func predicate) { int removed = 0; SinglyLinkedListNode node = this; while (!Object.ReferenceEquals(node.next, this)) { if (predicate(node.next.value)) { node.next = node.next.next; ++removed; } node = node.next; } return removed; } #endregion #region IEnumerable Members public IEnumerator GetEnumerator() { return new Enumerator(this); } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion #region Implementation Classes class Enumerator : IEnumerator { private SinglyLinkedListNode sentinel; private SinglyLinkedListNode cursor; internal Enumerator(SinglyLinkedListNode sentinel) { this.cursor = this.sentinel = sentinel; } #region IEnumerator Members public T Current { get { return cursor.value; } } #endregion #region IDisposable Members public void Dispose() { sentinel = null; cursor = null; } #endregion #region IEnumerator Members object IEnumerator.Current { get { return Current; } } public bool MoveNext() { cursor = cursor.next; return cursor != sentinel; } public void Reset() { cursor = sentinel; } #endregion } #endregion } }