0

So, I wrote a quicksort algorythm and a hoare-partition algorythm. Somehow when I try to run the example case in main (), it hangs up on quickSort(test, 0,3). There seems to be an infinite loop. I don't see how to fix it, since the two functions individually seem to be fine.

I tried debugging, but I am fairly new to c. I noticed that quickSort(test,0,3) calls itself recursively. So I know the issue has something to do with high not decreasing. But I took example pseudo code from an university slide to built the function and everything seems to line up.

void printArray(int A[], int high) {
    for (int i=0; i<=high; i++) {
         printf("%d ", A[i]);
    }
}

int partitionHoare(int A[], int low, int high) {
    int pivot=A[low];
    int left = low-1;
    int right= high+1;

    while (1){
        while (1){
            left++;
            if (A[left]>=pivot) break;
        }
        while (1){
            right--;
            if (A[right]<=pivot) break;
        }


        if (left<right)  {
            int temp=A[left];
            A[left]=A[right];
            A[right]=temp;
        }
        else return left;
    }
}

void quicksort(int A[], int low, int high){
    if (low<high){
        int middle=partitionHoare(A,low, high);
        quicksort(A, low,middle-1);
        quicksort(A, middle, high);
    }
}


void main (){
    int test[]={64,81,24,42,90,30,9,95};
    quicksort(test,0,7);
    printArray(test,7);

I actually expect the test array to be printed out sorted like this: "9, 24, 30, 42, 64, 81, 90, 95"

  • please post a [mcve] so we can reproduce the problem and help you to debug it. – user3629249 Apr 25 '19 at 14:48
  • 2
    OT: regarding: `void main (){` The return type for main() is always `int`, never `void` – user3629249 Apr 25 '19 at 14:50
  • running the posted code (after adding `#include ` and a closing '}' brace at end of `main()`) the code results in a seg fault event, not a 'forever' running. The problem seems to originate at: ` quicksort(A, middle, high);` – user3629249 Apr 25 '19 at 14:53
  • So I changed the void main () to int main (), with no difference. What is a seg fault event and how can I handle it. As I said, I'm new to c and programming in general. – Joe Johnson Apr 25 '19 at 14:58
  • the source of the problem is in the function: `int partitionHoare(int A[], int low, int high) {` Suggest walking through that function with some representative values – user3629249 Apr 25 '19 at 15:02
  • Ok I'll try that and report back in. – Joe Johnson Apr 25 '19 at 15:05
  • I get a segfault, too, and Valgrind tells me that it arises (appropriately enough) from a stack overflow. It looks like your recursion is not terminating. – John Bollinger Apr 25 '19 at 15:12
  • suggest looking at the [qsort](https://www.tutorialspoint.com/c_standard_library/c_function_qsort.htm) algorithm – user3629249 Apr 25 '19 at 15:14
  • what is [hoare](https://en.wikipedia.org/wiki/Hoare_logic) about – user3629249 Apr 25 '19 at 15:16
  • partitionHoare divides the array into two unsorted sub arrays, where each element of the left subarray is smaller than each element in the right subarray. – Joe Johnson Apr 25 '19 at 15:24

2 Answers2

1

You have a logical deficiency in your quicksort() function:

void quicksort(int A[], int low, int high){
    if (low<high){
        int middle=partitionHoare(A,low, high);
        quicksort(A, low,middle-1);
        quicksort(A, middle, high);
    }
}

It does not ensure that the recursion will terminate.

Specifically, if, in some sub-array of length greater than 1, the first element is the least and is not a duplicate then partitionHoare() will return a value equal to low without modifying the array. In that case, the recursive call for the left subarray will do nothing, but the recursive call for the right subarray will reiterate the current arguments exactly. Nothing having changed, the same thing is then guaranteed to happen again, and again, indefinitely.

You could break the infinite recursion in that case by testing in quicksort() whether middle == low, but that doesn't give you a correct sort.

One common solution here is twofold:

  1. Ensure that the partition function swaps the pivot value to the pivot index it reports. This is certain to be a correct final position for that value.
  2. When recursing, exclude the pivot index (whose value we know is correct) from both sub-arrays, so that each sub-problem is certain to be smaller than the parent problem.
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

Change partition to return right (instead of left). Change the two recursive calls to | quicksort(A, low,middle); | quicksort(A, middle+1, high);. This will exactly match the wiki article's example:

https://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme

You may want to change the name of "middle". Wiki example calls it p meaning partition split index (as opposed to meaning index to pivot), since with Hoare partition scheme, the pivot and elements equal to the pivot may end up at the end of the left partition and/or at the start of the right partition.

rcgldr
  • 27,407
  • 3
  • 36
  • 61