Concepts / The QuickSort Algorithm

The QuickSort Algorithm

A separate thread is useful for animation when the thread runs a recursive algorithm and the display must be redrawn many times during the recursion.

  • Programming
Interactive lab

Try it: The Call Stack

How the call stack keeps track of function calls: each call pushes a frame with its own arguments and local variables, and each return pops it.

How it works

  1. Calling a function pushes a new frame on top of the stack; the caller pauses.
  2. The frame holds that call's parameters and local variables.
  3. When the function returns, its frame is popped and the return value goes back to the paused caller.
  4. A recursive function pushes one frame per call until the base case, then the frames unwind in reverse order.

Default run (17 steps): Program starts: main is about to call factorial(4). … The stack is empty again. Result: 24. Deepest point: 4 frames, 4 calls in total.

Educational simulation

Loading the simulation…

Watching a Sort Happen

Imagine wanting to watch a sorting algorithm work instead of just reading its output. A list of colors arrives in a random order, and over several seconds you see the colors move into place one step at a time. Each change on screen corresponds to a real step inside the algorithm. This article is about building that kind of animation for a recursive algorithm, using the QuickSort algorithm as the example.

The source gives a concrete program, QuicksortThreadDemo.java, that does exactly this. It animates a recursive QuickSort that sorts randomized colors into a standard spectrum running from red to violet, in slow motion. The Start button becomes a Finish button while the sort runs, which lets the user abort the sort before it finishes on its own.

A Recursive Algorithm Is One Method Calling Itself

A recursive algorithm solves a problem by having a method call itself on smaller pieces of the problem. The call stack grows and shrinks as the work proceeds, and the ordering of steps is determined by those nested calls. Each call that is still in progress is waiting for the calls it started to finish before it can complete.

This shape matters for animation. The algorithm is not organized as a list of separate, equally sized steps waiting to be taken one at a time. Its natural structure is one method that keeps calling itself until the job is done. The diagram below shows a simplified picture of this nesting. Each box is a sort call, and the calls below the top one are the smaller pieces it hands off. The top call is the one that started the work, and it cannot finish until the calls it started have finished.

sort call on wholelistwaitingsort call on asmaller piecewaitingsort call on an evensmaller piecerunningcallscalls
When a recursive sort is paused, where does each pending call wait, and how does the work continue from the same point? This simplified diagram shows the top call waiting on a smaller call, which in turn waits on an even smaller one.

Read the diagram from the top down. Only the innermost call is actively doing work at this moment. The calls above it are suspended in the middle of their own work, each holding its place in the chain. The diagram is a simplified picture of this control flow and does not show every internal call of QuickSort.

Why a Timer Makes Recursion Awkward

Now suppose you want to animate this algorithm with a timer that fires at regular intervals. The natural plan is that each tick advances the algorithm by one step, and the display is updated after each advance. The source states the difficulty directly: it is difficult to break up a recursive algorithm into a series of method calls driven by a timer.

The reason is the shape of the work. A timer naturally produces a sequence of separate calls, each one doing a small piece and returning. A recursive algorithm does not divide itself neatly that way. Its steps are dictated by nested calls, so the program would have to find a way to stop in the middle of a chain of calls, hand control back to the timer, and later resume at exactly the same place. That is what makes the timer-driven approach awkward.

one recursivemethod callruns in a threadtimer tickfires at intervalsmethod calls itselfnested callsone step method callreturns after one steprecursestriggers
How does the control flow of a recursive sort differ from a series of separate, timer-triggered method calls? The left column is the structure the source recommends; the right column is the structure that is difficult to build.

Giving the Recursion Its Own Thread

The source's recommended design is to run a single recursive method call inside a thread. This structure is easy to run in a thread. The thread can carry the entire recursion from start to finish while the rest of the program keeps responding. Once the user starts the sort, the thread takes over and runs the recursive QuickSort, and the rest of the program is free to handle other work, such as responding to the Finish button.

The reason to use a separate thread at all is that the display must be redrawn many times while the recursion is in progress. A thread gives the recursive work its own flow of control. Each time the algorithm reaches a point where something visible has changed, the program can update the display. Because the recursion runs in the thread, these redraws happen as part of the sorting process rather than as a separate schedule that must somehow keep up with it.

Main programhandles the userSorting threadruns recursive QuickSortDisplaydraws current colorsstart sortrecursive step changes arrangementsomething visible changedredraw colors
In what order do the sorting thread's steps and the display's repaints happen? Read the messages from top to bottom. The sorting thread changes the arrangement and asks for a repaint, and the display draws the current arrangement.

Redrawing the Display While the Sort Runs

Each change in the arrangement of colors is one visible event. The source describes the loop like this: each pass through the recursion can change the arrangement, and the display is refreshed as those changes happen. The loop from the decision back to the recursive call stands for the recursion continuing until nothing remains to sort.

Worked example

Tracing one redraw cycle

A list of four colors starts in a random order. Describe what repeats each time the display is refreshed while the recursive sort runs.

  1. 1
    Start the sort

    The user presses Start, and the sorting thread begins the recursive QuickSort. The display shows the colors in their random starting order.

  2. 2
    Make a change

    The recursion reaches a point where the arrangement of colors changes. The thread records that something visible has changed.

  3. 3
    Refresh the display

    The program redraws the colors so the screen shows the new arrangement. Because this happens inside the sorting flow, the picture matches the algorithm's current state.

  4. 4
    Continue the recursion

    The recursion keeps going on the smaller pieces it has not yet finished. Another change may follow, and another redraw will happen when it does.

  5. 5
    Stop when nothing remains

    The loop ends when the recursion has nothing left to sort. The final redraw shows the colors arranged from red to violet.

Result

Each cycle repeats the same pattern: the sorting thread changes the arrangement, the change is shown on screen, and the recursion continues. The display is redrawn many times, and each redraw reflects a real step of the algorithm.

The array of colors is the state that connects the two halves of the program. The sorting thread changes that array, and the drawing code reads the array's current contents to decide what to show. Since both use the same array, the picture on screen reflects the array as the recursion leaves it at that moment.

Mistakes When Animating a Recursive Sort

  • Common mistake

    Splitting the recursion into timer ticks because it looks like a list of steps

    What it looks like

    Trying to advance a recursive sort by one call each time a timer fires.

    Why it fails

    The source states that it is difficult to break a recursive algorithm into a series of timer-driven method calls, because its natural structure is one method that keeps calling itself.

    Do this instead

    Keep the recursive sort as a single method call and run it in a thread that carries it from start to finish.

  • Common mistake

    Assuming the display will update itself without any redraw

    What it looks like

    Changing the array during the sort and expecting the screen to show the change automatically.

    Why it fails

    The display must be redrawn many times during the recursion. The screen does not reflect the array unless the program asks for a redraw.

    Do this instead

    Request a redraw each time the algorithm reaches a point where something visible has changed.

  • Common mistake

    Thinking the thread is only there to make the program faster

    What it looks like

    Adding a thread expecting the sort to finish sooner.

    Why it fails

    The source gives the reason for the thread as the need to redraw the display many times while the recursion is in progress, not speed.

    Do this instead

    Use the thread to give the recursive work its own flow of control so that redraws happen as part of the sorting process.

Practice: Explaining the Design Choice

MEDIUM

A teammate proposes animating a recursive QuickSort by putting one timer tick in front of each recursive call, so that every call waits for the next tick before it runs. Using the ideas in this article, explain why this design is awkward and describe the structure the source recommends instead.

Hints
  • Think about what the source says is difficult: breaking a recursive algorithm into a series of timer-driven method calls.
  • Consider where the recursion would have to pause and how it would resume from the same point.
  • The recommended structure keeps the recursive method whole and runs it inside a thread.

Key Takeaways

  • A recursive algorithm is naturally one method that calls itself on smaller pieces, so its structure is not a list of equal steps that a timer can easily advance.
  • Splitting a recursive algorithm into a series of timer-driven method calls is difficult, so the source recommends running a single recursive method call inside a thread.
  • The thread carries the whole recursion while the rest of the program keeps responding, and the display is redrawn each time something visible changes.
  • The array of colors is the shared state: the sorting thread changes it and the drawing code reads it to show the current arrangement.