A stable variant of selection sort that preserves the relative order of equal elements by shifting instead of swapping.
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 of length , reorder it such that
and equal elements retain their original relative order.
Algorithm
For each position , find the minimum element in . Store it, shift all elements between and its position one step to the right, then insert the minimum at position .
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] = keyExample
Let
where the second component indicates original order.
Step 1:
Minimum is
Shift elements:
→ [(2,b), (4,a), (2,c), (3,d)]
Step 2:
Minimum in remaining is
→ [(2,b), (2,c), (4,a), (3,d)]
Final result:
Relative order of equal keys is preserved.
Correctness
At each iteration, the smallest remaining element is inserted at position . 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 | ||
| worst | ||
| average |
Shifting increases the number of assignments, but asymptotic time remains:
Space complexity:
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 afunc 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
}
}