/// <summary> /// Create or get an element in the vector. /// </summary> /// <param name="index">Index in the vector</param> /// <returns>The vector element at the specified index</returns> public VectorElement <T> GetElement(int index) { if (index < 0) { throw new ArgumentException("Invalid index {0}".FormatString(index)); } if (index == 0) { return(_trashCan); } // Expand the vector if it is necessary if (index > Length) { Length = index; } // Find the element SparseVectorElement element = _firstInVector, lastElement = null; while (element != null) { if (element.Index > index) { break; } if (element.Index == index) { return(element); } lastElement = element; element = element.NextInVector; } // Create a new element var result = new SparseVectorElement(index); // Update links for last element if (lastElement == null) { _firstInVector = result; } else { lastElement.NextInVector = result; } result.PreviousInVector = lastElement; // Update links for next element if (element == null) { _lastInVector = result; } else { element.PreviousInVector = result; } result.NextInVector = element; return(result); }
/// <summary> /// Swap two elements. /// </summary> /// <param name="index1">The index of the first element.</param> /// <param name="index2">The index of the second element.</param> public void Swap(int index1, int index2) { if (index1 < 0 || index2 < 0) { throw new SparseException("Invalid indices {0} and {1}".FormatString(index1, index2)); } if (index1 == index2) { return; } if (index2 < index1) { var tmp = index1; index1 = index2; index2 = tmp; } // Get the two elements SparseVectorElement first = null, second = null; // Find first element var element = _firstInVector; while (element != null) { if (element.Index == index1) { first = element; } if (element.Index > index1) { break; } element = element.NextInVector; } // Find second element while (element != null) { if (element.Index == index2) { second = element; } if (element.Index > index2) { break; } element = element.NextInVector; } // Swap these elements Swap(first, second, index1, index2); }
/// <summary> /// Remove an element. /// </summary> /// <param name="element">Element to be removed.</param> private void Remove(SparseVectorElement element) { // Update surrounding links if (element.PreviousInVector == null) { _firstInVector = element.NextInVector; } else { element.PreviousInVector.NextInVector = element.NextInVector; } if (element.NextInVector == null) { _lastInVector = element.PreviousInVector; } else { element.NextInVector.PreviousInVector = element.PreviousInVector; } }
/// <summary> /// Swaps the specified elements. /// </summary> /// <param name="first">The first element.</param> /// <param name="second">The second element.</param> /// <param name="index1">The index of the first element.</param> /// <param name="index2">The index of the second element.</param> private void Swap(SparseVectorElement first, SparseVectorElement second, int index1, int index2) { // Nothing to do if (first == null && second == null) { return; } // Swap the elements if (first == null) { // Do we need to move the element? if (second.PreviousInVector == null || second.PreviousInVector.Index < index1) { second.Index = index1; return; } // Move the element back var element = second.PreviousInVector; Remove(second); while (element.PreviousInVector != null && element.PreviousInVector.Index > index1) { element = element.PreviousInVector; } // We now have the element below the insertion point if (element.PreviousInVector == null) { _firstInVector = second; } else { element.PreviousInVector.NextInVector = second; } second.PreviousInVector = element.PreviousInVector; element.PreviousInVector = second; second.NextInVector = element; second.Index = index1; } else if (second == null) { // Do we need to move the element? if (first.NextInVector == null || first.NextInVector.Index > index2) { first.Index = index2; return; } // Move element forward var element = first.NextInVector; Remove(first); while (element.NextInVector != null && element.NextInVector.Index < index2) { element = element.NextInVector; } // We now have the first element above the insertion point if (element.NextInVector == null) { _lastInVector = first; } else { element.NextInVector.PreviousInVector = first; } first.NextInVector = element.NextInVector; element.NextInVector = first; first.PreviousInVector = element; first.Index = index2; } else { // Are they adjacent or not? if (first.NextInVector == second) { // Correct surrounding links if (first.PreviousInVector == null) { _firstInVector = second; } else { first.PreviousInVector.NextInVector = second; } if (second.NextInVector == null) { _lastInVector = first; } else { second.NextInVector.PreviousInVector = first; } // Correct element links first.NextInVector = second.NextInVector; second.PreviousInVector = first.PreviousInVector; first.PreviousInVector = second; second.NextInVector = first; first.Index = index2; second.Index = index1; } else { // Swap surrounding links if (first.PreviousInVector == null) { _firstInVector = second; } else { first.PreviousInVector.NextInVector = second; } first.NextInVector.PreviousInVector = second; if (second.NextInVector == null) { _lastInVector = first; } else { second.NextInVector.PreviousInVector = first; } second.PreviousInVector.NextInVector = first; // Swap element links var element = first.PreviousInVector; first.PreviousInVector = second.PreviousInVector; second.PreviousInVector = element; element = first.NextInVector; first.NextInVector = second.NextInVector; second.NextInVector = element; first.Index = index2; second.Index = index1; } } }