Sorting Algorithms Overview
Unsorting is the reverse goal of sorting: it aims for a random arrangement rather than an ordered one.
Reversing the Goal of Sorting
Most of the sorting techniques you have studied start from a jumbled collection and produce an ordered one. This article turns that goal around. Instead of asking how to arrange values from smallest to largest, we ask how to arrange them so that the final order is unpredictable. The everyday picture is a deck of playing cards. Before a game, the cards are mixed so that no one can guess what comes next. That mixing is the problem this article solves, and it is the reverse of the problem sorting solves.
The source material presents this as a related problem that is less common than sorting but interesting to study in its own right. Because it uses the same kind of array and the same kind of step-by-step movement that sorting uses, it is a good way to check whether you understand how those movements work.
Sorting Versus Unsorting
Unsorting is the reverse goal of sorting: it aims for a random arrangement rather than an ordered one.
Unsorting is closely related to sorting. Both work on the same data structure and both rearrange its elements. The difference lies in what decides each move. A sorting algorithm uses the values themselves to decide where things belong. An unsorting algorithm uses chance to decide where things go. Keeping that difference in mind will help you understand every later step in this article.
| Aspect | Sorting | Unsorting (shuffling) |
|---|---|---|
| Goal | An ordered arrangement, smallest to largest | A random arrangement with an unpredictable final order |
| What decides each move | The values themselves tell the algorithm where things belong | Chance decides where things go |
| Data structure | An array | The same kind of array |
| Movement | Elements are rearranged step by step | Elements are rearranged step by step |
Sorting and unsorting share a data structure and a style of movement but differ in what drives each decision.
Borrowing Selection Sort's Skeleton
A good shuffling algorithm is built on the same skeleton as selection sort. Recall how selection sort works: it repeatedly looks through the part of the array that is not yet finished, finds the biggest item, and moves that item to the end of the unfinished part. Each pass fixes one more position at the end, and the unfinished part shrinks until nothing is left.
The shuffle keeps this skeleton and changes exactly one decision. Where selection sort chooses the biggest item, the shuffle chooses an item at random. The chosen item is then moved to the end of the unfinished part, just as selection sort moves its biggest item. Because the structure is the same, every pass still settles one position and the work still shrinks from one pass to the next. Only the choice of which item to settle has changed.
Tracing a Shuffle by Hand
The best way to see the mechanism is to run it on paper. Work with a four-value array: 7, 2, 5, 9 at indexes 0 through 3. At the start, the whole array is the unfinished part. Each pass does three things: pick one index in the unfinished part at random, exchange that value with the value at the last index of the unfinished part, and then treat that last index as settled so the unfinished part shrinks by one. The random picks below are chosen by hand for illustration, since the source does not fix any particular sequence.
Shuffling 7, 2, 5, 9 by hand
Starting from the array [7, 2, 5, 9], apply the shuffle pass by pass. Each pass picks a random index from the unfinished part, moves that value to the end of the unfinished part, and shrinks the unfinished part by one.
- 1Pass 1: unfinished part is indexes 0 to 3
Suppose the random pick lands on index 1, which holds 2. Exchange it with index 3, which holds 9. The array becomes [7, 9, 5, 2]. Index 3 now holds 2 and is settled, so the unfinished part is indexes 0 to 2.
- 2Pass 2: unfinished part is indexes 0 to 2
Suppose the random pick lands on index 0, which holds 7. Exchange it with index 2, which holds 5. The array becomes [5, 9, 7, 2]. Index 2 now holds 7 and is settled. Index 3 is not chosen again, because it is outside the unfinished part.
- 3Pass 3: unfinished part is indexes 0 to 1
Suppose the random pick lands on index 0, which holds 5. Exchange it with index 1, which holds 9. The array becomes [9, 5, 7, 2]. Index 1 now holds 5 and is settled, leaving only index 0 in the unfinished part.
- 4Finish: one position remains
With one index left in the unfinished part, there is nothing to exchange. The final array is [9, 5, 7, 2], which is a different arrangement from the start and was produced without comparing values to decide where anything belongs.
The final arrangement is [9, 5, 7, 2]. Every value was settled exactly once, and the unfinished part shrank from four positions to three, to two, to one.
Read the diagram as a snapshot. Index 3 is now settled because it sits at the end of the unfinished part and will not be chosen again. Indexes 1 and 3 changed in this pass, and the values at indexes 0 and 2 stayed where they were. The next pass will draw only from indexes 0 to 2, so the value 2 can never be picked again.
Choosing the Random Range
The one decision that matters most at each step is the range the random pick is drawn from. The correct range is the unfinished part, and that range must shrink after every pass. In the trace above, pass one drew from indexes 0 to 3, pass two from indexes 0 to 2, and pass three from indexes 0 to 1. The settled positions at the end of the array were never part of any later choice.
The range has to be right for two reasons. First, the shuffle must place each value exactly once, which only happens if each settled position is fixed and left alone. Second, the number of passes must be finite, which only happens if the unfinished part gets smaller each time. A range that is too wide breaks the first reason, and a range that never shrinks breaks the second.
Mistakes in Shuffle Design
The source identifies two main sources of error when building a shuffle. Both come from changing too little, or from changing the wrong thing.
Common mistake Choosing from settled values
What it looks likeOn pass two of the trace, the pick is drawn from indexes 0 to 3 instead of 0 to 2, so index 3, which already holds 2, can be chosen and moved again.
Why it failsA settled value has already been placed at the end of the unfinished part. Moving it again disturbs a position that the algorithm has already fixed, and the same value can be picked repeatedly.
Do this insteadDraw the random index only from the unfinished part, and shrink that part by one after every pass.
Common mistake Keeping the sorting rule unchanged
What it looks likeThe loop still picks the biggest item in the unfinished part, exactly as selection sort does.
Why it failsThe structure of selection sort is correct for sorting, but it produces an ordered arrangement. Keeping its choice rule means the output is sorted rather than shuffled.
Do this insteadReplace only the choice rule: pick a random item from the unfinished part. Leave the move to the end and the shrinking step as they are.
Common mistake Forgetting to shrink the range
What it looks likeEvery pass draws from the whole array of four indexes.
Why it failsWithout shrinking, a value can be chosen again and again, and the work has no clear point at which it ends.
Do this insteadAfter each pass, treat the last index of the unfinished part as settled and reduce the range by one.
Checking Your Own Trace
Before you read the answer, try this. Start with the array 4, 8, 1, 6 at indexes 0 to 3. Work through three passes by hand. In each pass, pick a random index from the unfinished part (choose any index you like, but write it down), exchange that value with the last index of the unfinished part, and shrink the unfinished part. After each pass, write the full array and list which indexes are settled. Check your answer by confirming that no settled index was chosen in a later pass and that the unfinished part shrank from four to three to two to one.
Hints
- Write the unfinished range before each pass, such as indexes 0 to 3, then 0 to 2, then 0 to 1.
- The exchange always involves the last index of the unfinished part, so the value that was there moves into the position you picked.
- If a settled index shows up as a pick, the range was wrong. Go back and draw only from the unfinished part.
Key Takeaways
- Unsorting is the reverse goal of sorting: it aims for a random arrangement rather than an ordered one, and chance replaces the values as the guide for each move.
- A shuffle reuses the skeleton of selection sort and changes exactly one decision: the biggest item is replaced by a randomly chosen item from the unfinished part.
- Each pass settles one position, so the unfinished part must shrink after every step; this shrinking is what makes the shuffle finish.
- The two main design errors are choosing from settled values and keeping the sorting rule unchanged, and both are avoided by drawing only from the unfinished part and changing only the choice rule.