1. Introduction
In this tutorial, we’ll see if Selection Sort is a stable or unstable algorithm.
2. Stable Sorting Algorithms
A sorting algorithm is stable if it keeps the relative order of equal elements.
For example, let be the array to sort. If , then a stable algorithm will place the item before the item in the sorted output.
2.1. Example
Let’s say that we want to sort a word array:
It contains two equal elements: the blue and the red . A stable sorting algorithm would put the blue before the red one in the sorted output because that’s their order in the input array:
Would Selection Sort do that? Is it a stable or unstable sorting algorithm?
3. The Standard Selection Sort Is Not Stable
Here’s the pseudocode of the usual formulation of Selection Sort:
algorithm SelectionSort(a, n):
// INPUT
// a = the input array with n elements
// OUTPUT
// a is sorted non-decreasingly (a[1] ≤ a[2] ≤ ... ≤ a[n-1] ≤ a[n])
// The outer loop invariant is that a[1 : (i-1)] is sorted
for i <- 1 to n:
// Find the index of the minimal element in the sub-array a[i : n]
j_min <- i
for j <- i to n:
if a[j] < a[j_min]:
j_min <- j
// Exchange a[j_min] with a[i] if necessary
if i != j_min:
temp <- a[i]
a[i] <- a[j_min]
a[j_min] <- temp
It repeatedly places the minimal elements of at positions , swapping the minimum of with the element . As a result, it may place after the elements it’s equal to when it exchanges it with the minimum of .
3.1. Example
Let’s work show how Selection Sort would handle our animal array:
In the first iteration of the outer for-loop, the algorithm determines that is the minimal element and exchanges it with the blue :
Then, it finds that the red is the minimal item in the rest of the array () and swaps it with :
Finally, since in the usual lexicographic order, Selection Sort swaps the red with :
As we see, that doesn’t maintain the relative order of the two strings. Since they are equal, the one that was initially before the other should come first in the output array. But, Selection Sort places the red before the blue one even though their initial relative order was opposite.
So, we can conclude that the standard formulation of Selection Sort isn’t stable.
4. Can We Make a Stable Variant of Selection Sort?
Instead of swapping the minimum of with in the -th iteration of the outer loop, we could delete the minimum from and insert it between and , effectively shifting the unsorted items one position to the right. That way, we change only place the element at the position it should take in the sorted array and don’t affect the relative order of other unsorted items.
4.1. Example
Let’s work out an example. Here’s how this new algorithm sorts the array from above:
As expected, the relative order of the blue and red s doesn’t change.
4.2. Pseudocode
Here’s the pseudocode:
algorithm StableSelectionSort(a, n):
// INPUT
// a = the input array with n elements
// OUTPUT
// a is sorted non-decreasingly (a[1] ≤ a[2] ≤ ... ≤ a[n-1] ≤ a[n])
// The outer loop invariant is that a[1 : (i-1)] is sorted.
for i <- 1 to n:
// Find the index of the minimal element in the sub-array a[i : n].
j_min <- i
for j <- i to n:
if a[j] < a[j_min]:
j_min <- j
// If j_min != i, place a[j_min] at the i-th position
// and shift the rest of unsorted elements one position to the right up to j_min.
if i != j_min:
temp <- a[j_min]
for j <- j_min to i + 1: // step -1
a[j] <- a[j-1]
a[i] <- temp
return a
4.3. Is This a Selection Sort?
The problem is that insertions and shifts aren’t present in the standard formulation of Selection Sort, only the exchanges. So, we could say that the algorithm we’ve just described isn’t a variant of Selection Sort.
However, there’s also ground to argue that it is. It preserves the main idea of Selection Sort: grow a sorted sub-array at the beginning of the array by repeatedly selecting the minimal elements of the unsorted part and placing them right at the end of the sorted sub-array. If we take that perspective, the insertions and shifts are nothing more than implementation details. Hence, they don’t change the logic, so the algorithm is a legitimate variant of Selection Sort.
4.4. Stable Selection Sort and Linked Lists
The problem with this Shift Selection Sort of ours is that, although stable, it does a lot of shifting. In the worst case, the minimal element will always be at the last position (), which happens when the array is sorted non-increasingly at the input. If that’s the case, there will be shifts in each outer loop’s iteration, which brings us to shifts in total:
That doesn’t make the time complexity worse compared with the standard formulation. But, it adds a computational burden that’s making the algorithm less efficient in practice.
A solution is to convert the array to a linked list. In that case, we don’t need to shift the elements. The only thing we need to do is redirect the pointer of to and the pointer of to .
5. Conclusion
In this article, we talked about the stability of Selection Sort. When applied to arrays, its standard formulation is unstable. However, we can modify it to be stable on both array and linked-list inputs.