From e3ca928636832814999d1e5daa89e7cd451d0e2d Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Wed, 2 Nov 2022 22:27:51 +0000 Subject: [PATCH] Implemented a messy QuickSort method for IList, appears to be working but needs to be cleaned and optimized still git-svn-id: file:///srv/devel/repo-conversion/nusu@338 d2e56fa2-650e-0410-a79f-9358c0239efd --- Source/Collections/IListExtensions.Test.cs | 15 ++++ Source/Collections/IListExtensions.cs | 84 ++++++++++++++++++++-- 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/Source/Collections/IListExtensions.Test.cs b/Source/Collections/IListExtensions.Test.cs index ae1b27e..215089b 100644 --- a/Source/Collections/IListExtensions.Test.cs +++ b/Source/Collections/IListExtensions.Test.cs @@ -60,6 +60,21 @@ namespace Nuclex.Support.Collections { ); } + /// Tests whether the insertion sort algorithm can be applied to 'Text' property works as expected + [Test] + public void QuickSortCanSortWholeList() { + var testList = new List(capacity: 5) { 1, 5, 2, 4, 3 }; + var testListAsIList = (IList)testList; + + testListAsIList.QuickSort(Comparer.Default); + + CollectionAssert.AreEqual( + new List(capacity: 5) { 1, 2, 3, 4, 5 }, + testList + ); + } + + } } // namespace Nuclex.Support.Collections diff --git a/Source/Collections/IListExtensions.cs b/Source/Collections/IListExtensions.cs index c00e025..5891a90 100644 --- a/Source/Collections/IListExtensions.cs +++ b/Source/Collections/IListExtensions.cs @@ -38,13 +38,10 @@ namespace Nuclex.Support.Collections { public static void InsertionSort( this IList list, int startIndex, int count, IComparer comparer ) { - int index = startIndex; - int endIndex = startIndex + count - 1; + int rightIndex = startIndex; - while(index < endIndex) { - int rightIndex = index; - - ++index; + int lastIndex = startIndex + count - 1; + for(int index = startIndex + 1; index <= lastIndex; ++index) { TElement temp = list[index]; while(rightIndex >= startIndex) { @@ -57,6 +54,8 @@ namespace Nuclex.Support.Collections { } list[rightIndex + 1] = temp; + + rightIndex = index; } } @@ -81,6 +80,79 @@ namespace Nuclex.Support.Collections { InsertionSort(list, Comparer.Default); } + /// + /// Sorts all the elements in an IList<T> using the quicksort 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; + + var spans = new Stack(); + spans.Push(0); + spans.Push(rightIndex); + + while(spans.Count > 0) { + int partitionRightEndIndex = spans.Pop(); + int partitionLeftEndIndex = spans.Pop(); + + int leftIndex = partitionLeftEndIndex + 1; + int pivotIndex = partitionLeftEndIndex; + rightIndex = partitionRightEndIndex; + + 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(partitionLeftEndIndex < rightIndex) { + spans.Push(partitionLeftEndIndex); + spans.Push(rightIndex - 1); + } + + if(partitionRightEndIndex > rightIndex) { + spans.Push(rightIndex + 1); + spans.Push(partitionRightEndIndex); + } + } + } + } } // namespace Nuclex.Support.Collections