CS 3100 Handout on Managing the stack when doing Quick Sort
Doing a recursive quick sort that manages the runtime stack:
Procedure Qsort (lo, hi) ;
BEGIN
/* This loop is used to eliminate the second recursive call. */
/* This algorithm keeps the runtime stack limited to size O(logN). */
WHILE (hi > lo) DO
BEGIN
Partition (lo, hi, splitPoint) ;
/* if the right half is larger */
IF (hi-splitPoint) > (splitPoint-lo)
THEN BEGIN
Qsort (lo, splitPoint) ; /* do the small (left) problem */
lo := splitPoint
END
ELSE BEGIN
Qsort(splitPoint, hi) ; /* do the small (right) problem */
hi := splitPoint
END
END
END ;
Doing a non-recursive quick sort that manages the "save-stack":
Push ({1, n}) ;
REPEAT
Pop ({lo,hi}) ;
WHILE lo < hi
BEGIN
Partition (lo, hi, splitPoint) ;
/* if the right half is larger */
IF (hi-splitPoint) > (splitPoint-lo)
THEN BEGIN
Push({splitPoint, hi}) ; /* put the big problem on the stack */
hi := splitPoint /* go to work on the small problem */
END
ELSE BEGIN
Push({lo,splitPoint}) ; /* put the big problem on the stack */
lo := splitPoint /* go to work on the small problem */
END
END ; /* while */
UNTIL stack is empty
You can also improve quicksort by making the base case a list of
size 10 or so. After the original call to quicksort completes
(which of course is also after all the recursive calls have
finished) a final call to insertion sort runs. This puts all the
small sublists into order more efficiently than recursive calls
to quicksort would have done.