/// <summary>
        /// removes last match only if count of available or visited elements
        /// is greater than 2,from question
        /// </summary>
        /// <param name="predicate"></param>
        public virtual void RemoveMatch(T predicate)
        {
            if (IsEmpty())
            {
                Debug.WriteLine($"Empty List : {predicate} not traced.", DebugSymbol);
                return;
            }

            int match = 0;

            DLinkedListNode <T> currentNode = _firstNode;

            for (int i = 0; i < Count; i++)
            {
                if (currentNode.Data.EqualsTo(predicate))
                {
                    Debug.WriteLine(currentNode.Data, "predicate");

                    if (match > 1)
                    {
                        //remove item and decrease match
                        DLinkedListNode <T> newPrevious = currentNode.Previous;

                        DLinkedListNode <T> newNext = currentNode.Next;

                        if (newPrevious != null)
                        {
                            newPrevious.Next = newNext;
                        }

                        if (newNext != null)
                        {
                            newNext.Previous = newPrevious;
                        }

                        currentNode = newPrevious;

                        --match;
                        --Count;
                    }
                    else
                    {
                        ++match;
                    }
                }
                if (currentNode.Next != null)
                {
                    currentNode = currentNode.Next;
                }
                else
                {
                    break;
                }
            }

            if (!WithinLimit(predicate))
            {
                RemoveMatch(predicate);
            }
        }
        /// <summary>
        /// add the specified dataItem at the beginning of the list.
        /// </summary>
        /// <param name="dataItem">Data item.</param>
        public virtual void Append(T dataItem)
        {
            DLinkedListNode <T> newNode = new DLinkedListNode <T>(dataItem);

            if (_firstNode == null)
            {
                _firstNode = _lastNode = newNode;
            }
            else
            {
                var currentNode = _firstNode;
                newNode.Next         = currentNode;
                currentNode.Previous = newNode;
                _firstNode           = newNode;
            }

            // Increment the count.

            if (!dataSet.Contains(dataItem))
            {
                dataSet.Add(dataItem);
            }

            _count++;
        }
        /// <summary>
        /// Add Last the specified dataItem at the end of the list.
        /// </summary>
        /// <param name="dataItem">Data item.</param>
        public virtual void Prepend(T dataItem)
        {
            DLinkedListNode <T> newNode = new DLinkedListNode <T>(dataItem);

            if (_firstNode == null)
            {
                //Prev->First->Prev Circular Linked List
                _firstNode = _lastNode = newNode;
            }
            else
            {
                //we dont loop here we operate at o(1)
                var currentNode = _lastNode;
                currentNode.Next = newNode;
                newNode.Previous = currentNode;
                _lastNode        = newNode;
            }

            if (!dataSet.Contains(dataItem))
            {
                dataSet.Add(dataItem);
            }
            // Increment the count.

            _count++;
        }
        /// <summary>
        /// Sets the value of the element at the specified index
        /// </summary>
        /// <param name="index">Index of element to update.</param>
        /// <returns>Element</returns>
        protected virtual void _setElementAt(int index, T value)
        {
            if (IsEmpty() || index < 0 || index >= Count)
            {
                Debug.WriteLine($"Empty List : {index} => {value} not set.", DebugSymbol);
                return;
            }



            if (index == 0)
            {
                _firstNode.Data = value;//O(1)
            }
            else if (index == (Count - 1))
            {
                _lastNode.Data = value;//O(1)
            }
            else
            {
                // Decide from which reference to traverse the list,
                //and then move the currentNode reference to the index
                // If index > half then traverse it from the end (_lastNode reference)
                // Otherwise, traverse it from the beginning (_firstNode refrence)
                //to run at O(1) ---traversing a node from the middle is O(1) we save time here

                DLinkedListNode <T> currentNode = null;

                if (index > (Count / 2))//_lastNode chooser
                {
                    currentNode = this._lastNode;

                    for (int i = 0; i < (Count - 1); ++i)
                    {
                        currentNode = currentNode.Previous;
                    }
                }
                else
                {
                    currentNode = this._firstNode;

                    for (int i = 0; i < index; ++i)
                    {
                        currentNode = currentNode.Next;
                    }
                }

                currentNode.Data = value;
            }
        }
        /// <summary>
        /// Inserts the dataItem at the specified index.
        /// </summary>
        /// <param name="dataItem">Data item.</param>
        /// <param name="index">Index.</param>
        public virtual void InsertAt(T dataItem, int index)
        {
            if (index < 0 || index > Count)
            {
                Debug.WriteLine("Index out of bound", DebugSymbol);
                return;
            }

            if (index == 0)
            {
                Append(dataItem);
            }
            else if (index == Count)
            {
                Prepend(dataItem);
            }
            else
            {
                DLinkedListNode <T> currentNode = this._firstNode;

                for (int i = 0; i < index - 1; ++i)
                {
                    currentNode = currentNode.Next;
                }


                DLinkedListNode <T> newNode = new DLinkedListNode <T>(dataItem);

                var prevNext = currentNode.Next;

                if (prevNext != null)
                {
                    currentNode.Next.Previous = newNode;
                }

                newNode.Next     = prevNext;
                currentNode.Next = newNode;
                newNode.Previous = currentNode;

                _count++;
            }

            if (!dataSet.Contains(dataItem))
            {
                dataSet.Add(dataItem);
            }
        }
        /// <summary>
        /// Gets the element at the specified index
        /// </summary>
        /// <param name="index">Index of element</param>
        /// <returns>Element</returns>
        public virtual T _getElementAt(int index)
        {
            if (IsEmpty() || index < 0 || index >= Count)
            {
                Debug.WriteLine($"Empty List : {index} not traced.", DebugSymbol);
            }

            if (index == 0)
            {
                return(First);
            }

            if (index == (Count - 1))
            {
                return(Last);
            }

            DLinkedListNode <T> currentNode = null;

            // Decide from which reference to traverse the list, and then move the currentNode reference to the index
            // If index > half then traverse it from the end (_lastNode reference)
            // Otherwise, traverse it from the beginning (_firstNode refrence)
            if (index > (Count / 2))
            {
                currentNode = this._lastNode;
                for (int i = (Count - 1); i > index; --i)
                {
                    currentNode = currentNode.Previous;
                }
            }
            else
            {
                currentNode = this._firstNode;
                for (int i = 0; i < index; ++i)
                {
                    currentNode = currentNode.Next;
                }
            }

            return(currentNode.Data);
        }
        /// <summary>
        /// Remove the specified dataItem.
        /// </summary>
        public virtual void RemoveFirstMatch(Predicate <T> predicate)
        {
            // Handle index out of bound errors
            if (IsEmpty())
            {
                Debug.WriteLine($"Empty List : {predicate.Target} not traced.", DebugSymbol);
                return;
            }

            if (predicate(_firstNode.Data))
            {
                _firstNode = _firstNode.Next;

                if (_firstNode != null)
                {
                    _firstNode.Previous = null;
                }
            }
            else if (predicate(_lastNode.Data))
            {
                _lastNode = _lastNode.Previous;

                if (_lastNode != null)
                {
                    _lastNode.Next = null;
                }
            }
            else
            {
                // Remove
                var currentNode = _firstNode;

                //Get currentNode to reference the element at the index.
                while (currentNode.Next != null)
                {
                    if (predicate(currentNode.Data))
                    {
                        break;
                    }

                    currentNode = currentNode.Next;
                }
                //end-while

                // If we reached the last node and item was not found
                // Throw exception
                if (!predicate(currentNode.Data))
                {
                    throw new Exception("Item was not found!");
                }

                // Remove element
                DLinkedListNode <T> newPrevious = currentNode.Previous;
                DLinkedListNode <T> newNext     = currentNode.Next;

                if (newPrevious != null)
                {
                    newPrevious.Next = newNext;
                }

                if (newNext != null)
                {
                    newNext.Previous = newPrevious;
                }

                currentNode = newPrevious;
            }

            // Decrement count.
            _count--;
        }
        /// <summary>
        /// Remove the specified dataItem.
        /// </summary>
        public virtual void Remove(T dataItem)
        {
            // Handle index out of bound errors
            if (IsEmpty())
            {
                Debug.WriteLine($"Empty List : {dataItem} not traced.", DebugSymbol);
                return;
            }

            if (_firstNode.Data.EqualsTo(dataItem))
            {
                _firstNode = _firstNode.Next;

                if (_firstNode != null)
                {
                    _firstNode.Previous = null;
                }
            }
            else if (_lastNode.Data.EqualsTo(dataItem))
            {
                _lastNode = _lastNode.Previous;

                if (_lastNode != null)
                {
                    _lastNode.Next = null;
                }
            }
            else
            {
                // Remove
                var currentNode = _firstNode;

                // Get currentNode to reference the element at the index.
                while (currentNode.Next != null)
                {
                    if (currentNode.Data.EqualsTo(dataItem))
                    {
                        break;
                    }

                    currentNode = currentNode.Next;
                }//end-while

                // Throw exception if item was not found
                if (!currentNode.Data.EqualsTo(dataItem))
                {
                    throw new Exception("Item was not found!");
                }

                // Remove element
                DLinkedListNode <T> newPrevious = currentNode.Previous;
                DLinkedListNode <T> newNext     = currentNode.Next;

                if (newPrevious != null)
                {
                    newPrevious.Next = newNext;
                }

                if (newNext != null)
                {
                    newNext.Previous = newPrevious;
                }

                currentNode = newPrevious;
            }

            // Decrement count.
            _count--;
        }
Beispiel #9
0
 public int CompareTo([AllowNull] DLinkedListNode <T> other)
 {
     return(other == null ? -1 : Data.CompareTo(other.Data));
 }
Beispiel #10
0
 public DLinkedListNode(T dataItem, DLinkedListNode <T> _next, DLinkedListNode <T> _previous)
 {
     this._data     = dataItem;
     this._next     = _next;
     this._previous = _previous;
 }