using System.Collections; using System.Collections.Generic; namespace BF { //双向循环列表 public class BFLinkedList : IEnumerable { public T FirstItem { get { return First == null ? default(T) : First.item; } } public T LastItem { get { return Last == null ? default(T) : Last.item; } } public BFNode First { get { return head; } } public BFNode Last { get { return head == null ? null : head.prev; } } private BFNode head; private int count; public int Count { get { return count; } } private int version; public int Version { get { return version; } } private BFStackPool nodePool; private IEqualityComparer comparer; public BFLinkedList(IEqualityComparer comp = null) { nodePool = new BFStackPool(); comparer = comp ?? EqualityComparer.Default; } public BFNode AddFirst(T t) { var newNode = nodePool.SafePop(); //Alloc(); newNode.item = t; if (null == head) { newNode.prev = newNode.next = newNode; head = newNode; ++count; ++version; } else { InternalInsertNodeBefore(head, newNode); head = newNode; } return null; } public BFNode AddLast(T t) { var newNode = nodePool.SafePop();//Alloc(); newNode.item = t; if (count == 0) { newNode.prev = newNode.next = newNode; head = newNode; ++count; ++version; } else InternalInsertNodeBefore(head, newNode); return newNode; } public void AddBefore(BFNode node, T t) { var newNode = nodePool.SafePop();//Alloc(); newNode.item = t; InternalInsertNodeBefore(node, newNode); if (node == head) head = newNode; } public void AddAfter(BFNode node, T t) { var newNode = nodePool.SafePop();//Alloc(); newNode.item = t; if (null == node.next) { node.next = newNode; newNode.prev = node; } else { InternalInsertNodeBefore(node.next, newNode); } } public bool Contains(T value) { return null != Find(value); } public BFNode Find(T value) { var node = head; if (null == node) return null; do { if (comparer.Equals(node.item, value)) return node; node = node.next; } while (node != head); return null; } public BFNode FindLast(T value) { if (null == head) return null; var last = head.prev; var node = last; do { if (comparer.Equals(node.item, value)) return node; node = node.prev; } while (last != node); return null; } public void Remove(T value) { var node = Find(value); if (node == null) return; InternalRemoveNode(node); } public void Clear() { var current = head; while (current != null) { var temp = current; current = current.next; temp.Invalidate(); nodePool.Push(temp); } } private void InternalRemoveNode(BFNode node) { if (node.next == node) { head = null; } else { node.next.prev = node.prev; node.prev.next = node.next; if (head == node) head = node.next; } node.Invalidate(); nodePool.Push(node); --count; ++version; } private void InternalInsertNodeBefore(BFNode node, BFNode newNode) { newNode.next = node; newNode.prev = node.prev; node.prev.next = newNode; node.prev = newNode; ++count; ++version; } public IEnumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(this); } public class Enumerator : IEnumerator { #region interface public T Current { get { return current; } } object System.Collections.IEnumerator.Current { get { return current; } } public bool MoveNext() { CheckInvalidOperation(); if (node == null) { index = linkedList.Count + 1; return false; } ++index; current = node.item; node = node.next; if (node == linkedList.head) node = null; return true; } public void Reset() { CheckInvalidOperation(); current = default(T); node = linkedList.head; version = linkedList.Version; index = 0; } public void Dispose() { linkedList = null; current = default(T); node = null; } #endregion private T current; private BFNode node; private int version; private int index; public BFLinkedList linkedList; public Enumerator(BFLinkedList ll) { linkedList = ll; node = ll.head; version = ll.Version; current = default(T); index = 0; } private void CheckInvalidOperation() { if (version != linkedList.Version) throw new System.InvalidOperationException("foreach 不能修改结构"); } } } }