Created a separate 'Partition' structure for the QuickSort() method so the Stack (used to avoid recursion) is a bit cleaner

git-svn-id: file:///srv/devel/repo-conversion/nusu@339 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2022-11-02 22:39:33 +00:00
parent e3ca928636
commit a10d30e6ea

View File

@ -27,6 +27,32 @@ namespace Nuclex.Support.Collections {
/// <summary>Extension methods for the IList interface</summary> /// <summary>Extension methods for the IList interface</summary>
public static class ListExtensions { public static class ListExtensions {
#region struct Partition
/// <summary>
/// Stores the left and right index of a partition for the quicksort algorithm
/// </summary>
private struct Partition {
/// <summary>
/// Initializes a new partition using the specified left and right index
/// </summary>
/// <param name="leftmostIndex">Index of the leftmost element in the partition</param>
/// <param name="rightmostIndex">Index of the rightmost element in the partition</param>
public Partition(int leftmostIndex, int rightmostIndex) {
this.LeftmostIndex = leftmostIndex;
this.RightmostIndex = rightmostIndex;
}
/// <summary>Index of the leftmost element in the partition</summary>
public int LeftmostIndex;
/// <summary>Index of the rightmost element in the partition</summary>
public int RightmostIndex;
}
#endregion // struct Partition
/// <summary> /// <summary>
/// Sorts a subset of the elements in an IList&lt;T&gt; using the insertion sort algorithm /// Sorts a subset of the elements in an IList&lt;T&gt; using the insertion sort algorithm
/// </summary> /// </summary>
@ -91,17 +117,15 @@ namespace Nuclex.Support.Collections {
) { ) {
int rightIndex = list.Count - 1; int rightIndex = list.Count - 1;
var spans = new Stack<int>(); var remainingPartitions = new Stack<Partition>();
spans.Push(0); remainingPartitions.Push(new Partition(0, rightIndex));
spans.Push(rightIndex);
while(spans.Count > 0) { while(remainingPartitions.Count > 0) {
int partitionRightEndIndex = spans.Pop(); Partition currentPartition = remainingPartitions.Pop();
int partitionLeftEndIndex = spans.Pop();
int leftIndex = partitionLeftEndIndex + 1; int leftIndex = currentPartition.LeftmostIndex + 1;
int pivotIndex = partitionLeftEndIndex; int pivotIndex = currentPartition.LeftmostIndex;
rightIndex = partitionRightEndIndex; rightIndex = currentPartition.RightmostIndex;
TElement pivot = list[pivotIndex]; TElement pivot = list[pivotIndex];
@ -141,14 +165,12 @@ namespace Nuclex.Support.Collections {
} }
} }
if(partitionLeftEndIndex < rightIndex) { if(currentPartition.LeftmostIndex < rightIndex) {
spans.Push(partitionLeftEndIndex); remainingPartitions.Push(new Partition(currentPartition.LeftmostIndex, rightIndex - 1));
spans.Push(rightIndex - 1);
} }
if(partitionRightEndIndex > rightIndex) { if(currentPartition.RightmostIndex > rightIndex) {
spans.Push(rightIndex + 1); remainingPartitions.Push(new Partition(rightIndex + 1, currentPartition.RightmostIndex));
spans.Push(partitionRightEndIndex);
} }
} }
} }