Stable Selection Sort
A stable variant of selection sort that preserves the relative order of equal elements by shifting instead of swapping.
Stable Selection Sort
Stable selection sort modifies selection sort to preserve the relative order of equal elements. Instead of swapping the minimum element into position, it removes the minimum and shifts the intervening elements right by one position.
This ensures stability at the cost of additional data movement.
Problem
Given a sequence $A$ of length $n$, reorder it such that
$$ A[0] \le A[1] \le \cdots \le A[n-1] $$
and equal elements retain their original relative order.
Algorithm
For each position $i$, find the minimum element in $[i, n-1]$. Store it, shift all elements between $i$ and its position one step to the right, then insert the minimum at position $i$.
stable_selection_sort(A):
n = length(A)
for i from 0 to n - 1:
min_index = i
for j from i + 1 to n - 1:
if A[j] < A[min_index]:
min_index = j
key = A[min_index]
while min_index > i:
A[min_index] = A[min_index - 1]
min_index = min_index - 1
A[i] = key
Example
Let
$$ A = [(4,a), (2,b), (2,c), (3,d)] $$
where the second component indicates original order.
Step 1:
Minimum is $(2,b)$
Shift elements:
→ [(2,b), (4,a), (2,c), (3,d)]
Step 2:
Minimum in remaining is $(2,c)$
→ [(2,b), (2,c), (4,a), (3,d)]
Final result:
$$ [(2,b), (2,c), (3,d), (4,a)] $$
Relative order of equal keys is preserved.
Correctness
At each iteration, the smallest remaining element is inserted at position $i$. Since elements are shifted rather than swapped, no equal elements change their relative order. The invariant that the prefix is sorted and stable holds throughout execution.
Complexity
| case | comparisons | time |
|---|---|---|
| best | $\frac{n(n-1)}{2}$ | $O(n^2)$ |
| worst | $\frac{n(n-1)}{2}$ | $O(n^2)$ |
| average | $\frac{n(n-1)}{2}$ | $O(n^2)$ |
Shifting increases the number of assignments, but asymptotic time remains:
$$ O(n^2) $$
Space complexity:
$$ O(1) $$
Properties
- stable
- in-place
- more writes than standard selection sort
When to Use
This variant is useful when stability is required but selection sort’s structure is preferred, such as in constrained environments where auxiliary memory must remain constant.
Implementation
def stable_selection_sort(a):
n = len(a)
for i in range(n):
min_idx = i
for j in range(i + 1, n):
if a[j] < a[min_idx]:
min_idx = j
key = a[min_idx]
while min_idx > i:
a[min_idx] = a[min_idx - 1]
min_idx -= 1
a[i] = key
return a
func StableSelectionSort[T constraints.Ordered](a []T) {
n := len(a)
for i := 0; i < n; i++ {
minIdx := i
for j := i + 1; j < n; j++ {
if a[j] < a[minIdx] {
minIdx = j
}
}
key := a[minIdx]
for minIdx > i {
a[minIdx] = a[minIdx-1]
minIdx--
}
a[i] = key
}
}