/// <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--; }
public int CompareTo([AllowNull] DLinkedListNode <T> other) { return(other == null ? -1 : Data.CompareTo(other.Data)); }
public DLinkedListNode(T dataItem, DLinkedListNode <T> _next, DLinkedListNode <T> _previous) { this._data = dataItem; this._next = _next; this._previous = _previous; }