1

I'm trying to implement quicksort in C.

I've done it before in Python, but I'm new to C and trying it out (please don't suggest I just use qsort()!)

What I don't understand is that since C doesn't handle arrays in the same way as Python, i.e. it can't pass them to and return them from functions, can only pass a pointer to one (or rather, the start of a space) in memory - how then can an array be used in a recursive function?

If my first call takes float array[], chooses a pivot, and sorts it. How can I then make successive calls for the lower and upper partitions, and glue them back together?!

Unless I'm mistaken, the glueing together requires an iteration through, since you can't assign to an array. But we can't do that, because we don't know how much memory we need on each call - and the spaces need to be different, because we still need the one higher (on earlier call)...

I've tried code, I've tried pen and paper, I just can't make this work - I understand recursion conceptually (and practically, in Python), I just can't see how to do this in C. I expect there's some functionality or syntax I just don't know about.

Grateful as ever.

OJFord
  • 10,522
  • 8
  • 64
  • 98

3 Answers3

0

As far as I know, most implementations of the Quicksort algorithm in C sort a given array "in-situ", and do not return a new sorted array.

A very simple implementation that might be useful to understand the method is shown here:

As you can see, the function just passes the same array with modified begin/end index to the recursively called function. Arrays decay into pointers to the first element when passed to a function, so all recursively called functions operate on (a part of) the same original array.

Other implementations might replace the recursion by iteration or tail-recursion, see for example

which has links to real-world implementations.

Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
0

Python variables are accessed using a handle to the variable allowing Python to manage variables by knowing their size and the data type and whether the variable is in scope or not or in use or not for garbage collection. In C source code a variable represents an actual memory location.

An array variable in Python is a handle to an array which Python stores in memory along with information about the array such as its size (number of elements), the type of the data stored in the array, etc. In C an array variable is basically a constant pointer to some memory location that contains the array elements. However there is no management data stored along with the array. The only thing in the array's memory location is the data for the array elements. The information about the array's size, data type, etc. is lost after compiling the C source code and is not available at run time.

In Python you can cut and splice and copy array and array pieces because the information about the array is available at run time. In C it is not so simple because the information about the array is not available after the source code is compiled.

The problem faced by the designer of a generalized qsort() function is that it must have an interface that allows the function to be used with a wide variety of arrays. And since the information about the array is not available at run time with C, the programmer must ask for the minimum information needed to make the qsort() function work for a wide variety of arrays.

What the programmer needs to know is the following basic information: (1) where does the array start, (2) what is the size of each element of the array, (3) how many elements are in the array, and (4) what is the comparison function to be used to determine the collating sequence to determine the order of two elements of the array.

The array is sorted in place. What that means is that you pass to the qsort() function the array and when qsort() returns the elements of the array have been sorted. This sorting is done by selecting two elements, comparing them with the comparison function provided, and then if needed swapping the two array elements. Remember that in C an array is basically a constant pointer to an area of memory. So the qsort() function is provided that address, where the array starts, and the caller expects that the array starting at that memory location is sorted when qsort() returns.

Since the comparison function is provided by the user of qsort(), the person writing the comparison function knows what the array elements looks like. The programmer uses the pointers provided by the qsort() function when it calls the comparison function to access the two array elements and decide the order of those two elements returning an indication as to which is lower in the collating sequence.

However the swapping of array elements requires the use of a temporary data area which runs back into the problem of the qsort() function when written did not know the size of the array elements. So the swap is usually done a byte at a time.

The end result of all of the various constraints due to the memory model of C is that a qsort() function will use recursion by specifying array index or array offset from the beginning of the array. So the qsort() function performs the sort on a subsection of the array by specifying the beginning and ending indices of the subsection. What is changing during the recursive function calls is just the index values.

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
0

"The C Programming Language" has an implementation of qsort. I'll copy and paste the code directly:

void qsort(int v[], int left, int right) {
    int i, last;
    void swap(int v[], int i, int j);
    int test = 100;

    if (left >= right)
        return;
    swap(v, left, (left+right)/2);
    last = left;
    for(i = left+1; i <= right; i++)
        if (v[i] < v[left])
        swap(v, ++last, i);
    swap(v, left, last);
    qsort(v, left, last-1);
    qsort(v, last+1, right);
}

The key here is that you specify the left and right bounds of the array with int left and int right that you want to process. That's how you deal with the "lower and upper partitions, and glue them back together" part you're confused with.

You call qsort initially with qsort(array,0,length-1), where length is the number of elements in array.

JustinBlaber
  • 4,629
  • 2
  • 36
  • 57