The core concept of quick sorting is very simple. Given a list, a ‘pivot’ is chosen (any arbitrary element from the list). Now all elements of the list, greater than the pivot are moved to the right. And all elements of the list, smaller than the pivot are moved to the left. Thus we form two unsorted lists. One list is on the left of the pivot, consisting of elements smaller than the pivot. Another list is to the right of the pivot, consisting of elements greater than the list. But what is important here, is that the pivot element has found its place. Consider this list...

Observe that, even though the elements before and after ‘5’ are not sorted, ‘5’ has found the place it should be after the sorting happens. That is, now we have two unsorted lists and one element in the right place. All we have to do is do the same thing recursively for those two unsorted lists (3, 2, 1 and 7, 6) until there are no unsorted lists and all elements find their right place. This tutorial will not discuss recursion. It is discussed here.

We will try to implement in a C++ program which quick sorts an array. The program contains the following functions...

• Quicksort() which quick sorts a given array
• Split() which splits the array into two parts, one with smaller elements than the pivot and another with larger elements than the pivot

Quicksort() takes an array, the index of the first element and the index of the last element as arguments. This is necessary because, we need to do recursive calls to Quicksort() with subsections of the list. In the above example we first do Quicksort() for the entire list. Then we do Quicksort() for the first three elements. Then we do Quicksort() for the last two elements. For such reasons, Quicksort() will need the first and last element indexes. We must have in mind that, Quicksort() returns without making further recursions, when there is only one element i.e., first and last are the same. It is the responsibility of Quicksort() to choose a pivot. In our design, we will just consider the leftmost element of the list to be the pivot.

Split() takes an array, the pivot, the index of the first element and the index of the last element as arguments. There are many techniques to achieve this split. We will use the same technique that C.A.R.Hoare (the inventor of the quick sort algorithm) suggested. Split() shuttles the pivot element back and forth repeatedly until it zeroes in at the required place. Then Split() returns the ‘split-point’ i.e., the position where the pivot is. Consider the following example to understand this well.

12 15 5 26 30 8 17 23 33

12 is the pivot. The Split() function, starts from the rightmost element ‘33’, and compares it with the pivot. 33 is larger then the pivot 12. So 12 should be at the left of 33 (because lesser numbers come left to pivot and larger numbers go right to pivot). So, it compares the next element ‘23’ with the pivot. It is again larger then the pivot. ‘12’ should be to the left of ‘23’. So, it compares the next element ‘17’ with the pivot. Yet again, it is larger than the pivot. ‘12’ should be to the left of ‘17’ too. So, it compares the next element ‘8’ with the pivot. ‘8’ is lesser than the pivot. ‘12’ should be to the right of ‘8’. ‘12’ and ‘8’ are swapped. Remember that it is not essential that anything is sorted yet, our only goal is to put all numbers larger than ‘12’ to the right and all numbers lesser than ‘12’ to the left. Now the list is ordered as follows...

8 15 5 26 30 1217 23 33

The underlined numbers need not be considered again, because they are already pushed to their correct sides. ‘8’ is to the left and ‘17’, ‘23’ and ‘33’ are to the right. Now Split() starts again from the leftmost element ‘15’. But this time it searches for an element larger than ‘12’. ‘12’ and ‘15’ are compared. ‘15’ is larger then the pivot ‘12’. It should be to the right of ‘12’. They are swapped. Now the list looks like this...

812 5 26 30 15 17 23 33

Again, Split() starts from the rightmost element ‘30’ and compares it with pivot ‘12’. ‘30’ is larger and is already in its side (right of 12). The next element ‘26’ is also larger than ‘12’ and thus on the correct side. But the next element ‘5’ is lesser than ‘12’. It should be on the left side of ‘12’. So, they are swapped. Now the list is...

8 51226 30 15 17 23 33

There is no more elements to be compared with the pivot (you can see that from the fact that we have underlined all the other numbers). Split() has finished its job i.e., 12 has found its position on the sorted list. Split() returns the split-point which is nothing but the current position of 12.

Quicksort() uses this returned value to determine the boundaries of the two unsorted lists obtained namely, 0-1 and 3-8 because the split-point is 2. Quicksort() makes two recursive calls to itself for these two lists. With each call to Quicksort(), one element finds its position in the sorted list. So finally, all elements find their positions. That is the list gets sorted.

The following code implements the quick sort technique in a C++ program. I recommend you view this code in your own editor, because it looks best in a monospaced font. There are two PrintArray() functions inside the SplitArray() function which are commented out. You can uncomment these functions to observe the array in each step of the process.

Remember that this SplitArray() function is only one of the many ways this can be done. Don't fail to think about other ways of doing this.

The above tutorial discusses sorting in ascending order using quicksort technique. As exercises try doing a quick sort program, that sorts in the descending order. Programmers who have a bit more confidence can try a quicksort module for linked lists. The underlying principle is the same - divide and conquer.

I wonder if the performance of quicksort will be better than bubble sort or not.... Please tell me about this! It turns out that quick sort require many "subfunction" and fairly many line of code comparing to a few line to accomplish bubblesort.... If I input 10 9 8 7 6 5 4 3 2 1, and then it shows me that swap() occur ..18 times. A lots!

I wonder if the performance of quicksort will be better than bubble sort or not.... Please tell me about this! It turns out that quick sort require many "subfunction" and fairly many line of code comparing to a few line to accomplish bubblesort.... If I input 10 9 8 7 6 5 4 3 2 1, and then it shows me that swap() occur ..18 times. A lots!

In real world applications the quicksort is considerably faster than bubble sort. Your input would be an example of a worst case scenario, giving O(n^2), however the average case performance is O(n log n)! If you want to go even faster, look at heap sort. Heap sort exhibits O(n log n) performance even in the worst case scenario - although it isn't considered a very stable algorithm, so you probably shouldn't use it for value based data.