I've made a quicksort algorithm in c# that works when there are only 10 items in the array. When I increase this number it gets stuck in an infinite loop. This is the code where the issue lies:
while (true)
{
while (((IComparable)arrayToSort[left]).CompareTo(pivot) < 0)
{
left++;
}
while (((IComparable)arrayToSort[right]).CompareTo(pivot) > 0)
{
right--;
}
if (left < right) //This is where the loop becomes infinite.
{
object temp =arrayToSort[right];
arrayToSort[right] = arrayToSort[left];
arrayToSort[left] = temp;
reDrawer.reDrawSample(right, g, arrayToSort, picSamples); //This is used to draw lines that are sorted to make the sorting visual.
reDrawer.reDrawSample(left, g, arrayToSort, picSamples);
refresher.refreshPicture(picSamples); //This is used to refresh the image with the lines.
Thread.Sleep(20);
}
else
{
return right;
}
Both of the comparison while statements are false but this if is true, and I can't see a way out of it. It occurs when right == pivot or left == pivot.
Can anyone see the issue?
The array currently has 50 variables, and this issue only occurs at high numbers of variables. I don't want to use an array with less than 50 variables.
Here's the full method:
class Quick_Sort
{
/// <summary>
/// This subroutine creates a pivot and partitions the array accordingly.
/// </summary>
/// <param name="arrayToSort"></param>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public int partition(ArrayList arrayToSort, int left, int right)
{
int pivot = (int)arrayToSort[left];
ReDrawer reDrawer = new ReDrawer();
Refresher refresher = new Refresher();
while (true)
{
while (((IComparable)arrayToSort[left]).CompareTo(pivot) < 0)
{
left++;
}
while (((IComparable)arrayToSort[right]).CompareTo(pivot) > 0)
{
right--;
}
if (left < right)
{
object temp =arrayToSort[right];
arrayToSort[right] = arrayToSort[left];
arrayToSort[left] = temp;
reDrawer.reDrawSample(right, g, arrayToSort, picSamples);
reDrawer.reDrawSample(left, g, arrayToSort, picSamples);
refresher.refreshPicture(picSamples);
Thread.Sleep(speed);
}
else
{
return right;
}
}
}
/// <summary>
/// This recursive subroutine is responsible for sorting the array into the correct order after the individual partitions have been ordered.
/// </summary>
/// <param name="arr"></param>
/// <param name="left"></param>
/// <param name="right"></param>
public void sortArray(ArrayList arr, int left, int right)
{
if (left < right)
{
int pivot = partition(arr, left, right);
if (pivot > 1)
{
sortArray(arr, left, pivot - 1);
}
if (pivot + 1 < right)
{
sortArray(arr, pivot + 1, right);
}
}
}
}
When sortArray is called, left = 0, right = 49 & array is a random 50 element one-dimensional array.
You can ignore the references to reDrawer and refresher as these don't affect the sorting algorithm, they only draw the results in a picture box.
It occurs when right == pivot or left == pivot.
You are right, in that case you stop in/de-creasing left/right. You need to in/de-crease both atleast once in each iteration.
public int partition(ArrayList arrayToSort, int left, int right)
{
int pivot = (int)arrayToSort[left];
left--;
right++; //To prevent the first iteration from ignoring the outermost elements
ReDrawer reDrawer = new ReDrawer();
Refresher refresher = new Refresher();
while (true)
{
do
{
left++;
}while (((IComparable)arrayToSort[left]).CompareTo(pivot) < 0);
do
{
right--;
}while (((IComparable)arrayToSort[right]).CompareTo(pivot) > 0);
if (left < right)
{
object temp =arrayToSort[right];
arrayToSort[right] = arrayToSort[left];
arrayToSort[left] = temp;
reDrawer.reDrawSample(right, g, arrayToSort, picSamples);
reDrawer.reDrawSample(left, g, arrayToSort, picSamples);
refresher.refreshPicture(picSamples);
Thread.Sleep(speed);
}
else
{
return right;
}
}
}