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.