public void Clear()
        {
            if (_head == null)
            {
                return;
            }
            var current = _head;

            do
            {
                var temp = current;
                current = current.Next;
                temp.Invalidate();
            } while (current != _head);
            _head  = null;
            _count = 0;
            ++_version;
        }
 private void RemoveNode(DoublyLinkedListNode <T> node)
 {
     if (node == _head && _count == 1)
     {
         _head.Invalidate();
         _head = null;
     }
     else
     {
         if (ReferenceEquals(node, _head))
         {
             _head = node.Next;
         }
         node.Prev.Next = node.Next;
         node.Next.Prev = node.Prev;
         node.Invalidate();
     }
     --_count;
 }
        private static DoublyLinkedListNode <T> BuildLinkedList(IEnumerable <T> collection)
        {
            var head = new DoublyLinkedListNode <T>();
            var p    = head; // head.next points to the first node

            foreach (var item in collection)
            {
                var node = new DoublyLinkedListNode <T>(item);
                p.Next    = node;
                node.Prev = p;
                p         = p.Next;
            }
            // now p points to the last node
            p.Next = head.Next;
            if (p.Next != null)
            {
                p.Next.Prev = p;
            }
            return(head.Next);
        }
        public void RemoveRange(int index, int count)
        {
            if (index < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }
            if (_count < count + index)
            {
                throw new ArgumentException();
            }
            if (count == 0)
            {
                return;
            }

            var startNode = GetAt(index);
            var prevNode  = startNode.Prev;
            var lastNode  = startNode;

            for (var i = 0; i < count; i++)
            {
                var p = lastNode;
                lastNode = lastNode.Next;
                p.Invalidate();
            }
            if (_count == count)
            {
                _head = null;
            }
            else
            {
                prevNode.Next = lastNode;
                lastNode.Prev = prevNode;
            }
            _count -= count;
            ++_version;
        }
        public void InsertRange(int index, IEnumerable <T> collection)
        {
            if (collection == null)
            {
                throw new ArgumentNullException(nameof(collection));
            }
            if (index < 0 || index > _count)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }
            var arr   = collection.ToArray();
            var count = arr.Length;

            if (count == 0)
            {
                return;
            }

            var newNode = BuildLinkedList(arr);

            if (_head == null)
            {
                _head = newNode;
            }
            else
            {
                var node        = (index == _count) ? _head : GetAt(index);
                var nodePrev    = node.Prev;
                var newNodePrev = newNode.Prev;
                nodePrev.Next    = newNode;
                newNode.Prev     = nodePrev;
                newNodePrev.Next = node;
                node.Prev        = newNodePrev;
            }
            if (index == 0)
            {
                _head = newNode;
            }
            _count += count;
            ++_version;
        }
            public bool MoveNext()
            {
                if (_version != _list._version)
                {
                    throw new InvalidOperationException();
                }

                if (_node == null)
                {
                    _index   = _list.Count + 1;
                    _current = default(T);
                    return(false);
                }

                ++_index;
                _current = _node.Item;
                _node    = _node.Next;
                if (_node == _list._head)
                {
                    _node = null;
                }
                return(true);
            }
        private void Reverse(DoublyLinkedListNode <T> startNode, int maxCount)
        {
            if (startNode == null || maxCount <= 0)
            {
                return;
            }
            var p        = startNode;
            var prevNode = startNode.Prev;
            var lastNode = startNode;

            for (var i = 0; i < maxCount; i++)
            {
                var temp = p.Next;
                p.Next   = p.Prev;
                p.Prev   = temp;
                lastNode = p;
                p        = temp; // move forward p
                if (p == _head)
                {
                    break;
                }
            }
            if (!(ReferenceEquals(_head, startNode) && maxCount >= _count))
            {   // it means not reverse all the list
                var lastNodeNext = p;
                prevNode.Next     = lastNode;
                lastNode.Prev     = prevNode;
                startNode.Next    = lastNodeNext;
                lastNodeNext.Prev = startNode;
            }
            if (ReferenceEquals(_head, startNode))
            {
                _head = lastNode;
            }
            ++_version;
        }
        private static int RelativeIndexOf(DoublyLinkedListNode <T> startNode, T item, int maxCount, bool frontToBackOrder)
        {
            if (startNode == null)
            {
                return(-1);
            }
            var node = startNode;
            var c    = EqualityComparer <T> .Default;
            var i    = 0;

            do
            {
                if (c.Equals(node.Item, item))
                {
                    return(i);
                }
                if (i++ >= maxCount)
                {
                    break;
                }
                node = frontToBackOrder ? node.Next : node.Prev;
            } while (node != startNode);
            return(-1);
        }
 public DoublyCircularLinkedList()
 {
     _head    = null;
     _count   = 0;
     _version = 0;
 }
 public DoublyLinkedListNode(T item, DoublyLinkedListNode <T> prev, DoublyLinkedListNode <T> next)
     : base(2, item)
 {
     Next = next;
     Prev = prev;
 }