diff --git a/Nuclex.Support (net-4.0).csproj b/Nuclex.Support (net-4.0).csproj index 346adfe..65713bc 100644 --- a/Nuclex.Support (net-4.0).csproj +++ b/Nuclex.Support (net-4.0).csproj @@ -106,7 +106,9 @@ Deque.cs - + + IListExtensions.cs + @@ -119,7 +121,9 @@ ItemReplaceEventArgs.cs - + + ListSegment.cs + MultiDictionary.cs diff --git a/Source/Collections/IListExtensions.Test.cs b/Source/Collections/IListExtensions.Test.cs index 215089b..097e9ba 100644 --- a/Source/Collections/IListExtensions.Test.cs +++ b/Source/Collections/IListExtensions.Test.cs @@ -66,7 +66,7 @@ namespace Nuclex.Support.Collections { var testList = new List(capacity: 5) { 1, 5, 2, 4, 3 }; var testListAsIList = (IList)testList; - testListAsIList.QuickSort(Comparer.Default); + testListAsIList.QuickSort(); CollectionAssert.AreEqual( new List(capacity: 5) { 1, 2, 3, 4, 5 }, diff --git a/Source/Collections/IListExtensions.cs b/Source/Collections/IListExtensions.cs index b512525..ba46a0d 100644 --- a/Source/Collections/IListExtensions.cs +++ b/Source/Collections/IListExtensions.cs @@ -103,7 +103,7 @@ namespace Nuclex.Support.Collections { /// Type of elements the list contains /// List in which a subset will be sorted public static void InsertionSort(this IList list) { - InsertionSort(list, Comparer.Default); + InsertionSort(list, 0, list.Count, Comparer.Default); } /// @@ -111,68 +111,78 @@ namespace Nuclex.Support.Collections { /// /// Type of elements the list contains /// List in which a subset will be sorted + /// Index at which the sorting process will begin + /// Index one past the last element that will be sorted + /// Comparison function to use for comparing list elements + public static void QuickSort( + this IList list, int startIndex, int count, IComparer comparer + ) { + var remainingPartitions = new Stack(); + remainingPartitions.Push(new Partition(startIndex, startIndex + count - 1)); + + while(remainingPartitions.Count > 0) { + Partition current = remainingPartitions.Pop(); + int leftEnd = current.LeftmostIndex; + int rightEnd = current.RightmostIndex; + + int pivotIndex = quicksortPartition(list, leftEnd, rightEnd, comparer); + if(pivotIndex - 1 > leftEnd) { + remainingPartitions.Push(new Partition(leftEnd, pivotIndex - 1)); + } + if(pivotIndex + 1 < rightEnd) { + remainingPartitions.Push(new Partition(pivotIndex + 1, rightEnd)); + } + } + } + + /// + /// Sorts all the elements in an IList<T> using the insertion sort algorithm + /// + /// Type of elements the list contains + /// List in which a subset will be sorted /// Comparison function to use for comparing list elements public static void QuickSort( this IList list, IComparer comparer ) { - int rightIndex = list.Count - 1; + QuickSort(list, 0, list.Count, comparer); + } - var remainingPartitions = new Stack(); - remainingPartitions.Push(new Partition(0, rightIndex)); + /// + /// Sorts all the elements in an IList<T> using the insertion sort algorithm + /// + /// Type of elements the list contains + /// List in which a subset will be sorted + public static void QuickSort(this IList list) { + QuickSort(list, 0, list.Count, Comparer.Default); + } - while(remainingPartitions.Count > 0) { - Partition currentPartition = remainingPartitions.Pop(); + private static int quicksortPartition( + IList list, int firstIndex, int lastIndex, IComparer comparer + ) { + TElement pivot = list[lastIndex]; + + // Set the high index element to its proper sorted position + int nextIndex = firstIndex; + for(int index = firstIndex; index < lastIndex; ++index) { + if(comparer.Compare(list[index], pivot) < 0) { + TElement temp = list[nextIndex]; + list[nextIndex] = list[index]; + list[index] = temp; - int leftIndex = currentPartition.LeftmostIndex + 1; - int pivotIndex = currentPartition.LeftmostIndex; - rightIndex = currentPartition.RightmostIndex; - - TElement pivot = list[pivotIndex]; - - if(leftIndex > rightIndex) - continue; - - while(leftIndex < rightIndex) { - - while(leftIndex <= rightIndex) { - if(comparer.Compare(list[leftIndex], pivot) > 0) { - break; - } - ++leftIndex; - } - - while(leftIndex <= rightIndex) { - if(comparer.Compare(list[rightIndex], pivot) < 0) { - break; - } - - --rightIndex; - } - - if(rightIndex >= leftIndex) { - TElement temp = list[leftIndex]; - list[leftIndex] = list[rightIndex]; - list[rightIndex] = temp; - } - - } - - if(pivotIndex <= rightIndex) { - if(comparer.Compare(list[pivotIndex], list[rightIndex]) > 0) { - TElement temp = list[pivotIndex]; - list[pivotIndex] = list[rightIndex]; - list[rightIndex] = temp; - } - } - - if(currentPartition.LeftmostIndex < rightIndex) { - remainingPartitions.Push(new Partition(currentPartition.LeftmostIndex, rightIndex - 1)); - } - - if(currentPartition.RightmostIndex > rightIndex) { - remainingPartitions.Push(new Partition(rightIndex + 1, currentPartition.RightmostIndex)); + ++nextIndex; } } + + // Set the high index value to its sorted position + { + TElement temp = list[nextIndex]; + list[nextIndex] = list[lastIndex]; + list[lastIndex] = temp; + } + + // Returns the next sorting element location + return nextIndex; + } }