Selection Sort
Description
Selection Sort is a straightforward comparison-based sorting algorithm that operates on a simple yet effective principle: repeatedly selecting the smallest (or largest, depending on sorting order) element from the unsorted portion of the array and moving it to its correct position in the sorted portion. Despite its simplicity, understanding its mechanics provides valuable insight into fundamental sorting concepts.
The algorithm divides the input array into two conceptual regions: a sorted subarray that builds up from left to right, and an unsorted subarray that shrinks as the algorithm progresses. Initially, the sorted subarray is empty, and the entire array is considered unsorted. During each iteration, Selection Sort scans through the unsorted region to find the minimum element, then swaps it with the first element of the unsorted region. This process effectively expands the sorted region by one element while contracting the unsorted region by the same amount.
What distinguishes Selection Sort from other quadratic sorting algorithms is its consistency and minimal write operations. Unlike Bubble Sort, which may perform many swaps, Selection Sort performs exactly n-1 swaps for an array of n elements—one swap per iteration (except when the minimum element is already in the correct position). This makes it particularly useful when write operations are significantly more expensive than read operations, such as when working with flash memory or EEPROM storage.
However, this algorithm has a critical limitation: it always performs O(n²) comparisons regardless of the initial ordering of the data. Whether the array is already sorted, reverse sorted, or randomly arranged, Selection Sort will examine every element in the unsorted portion during each iteration. This lack of adaptability means it cannot take advantage of any existing order in the data, making it inefficient for large datasets or scenarios where the input might be partially sorted.
Another important characteristic is that Selection Sort is not stable. A stable sorting algorithm preserves the relative order of elements with equal values. Because Selection Sort swaps elements across potentially large distances in the array, it can inadvertently change the relative positions of equal elements, which may be undesirable when sorting complex objects by one of multiple fields.
How It Works
Selection Sort operates through a systematic process of partitioning the array into two conceptual regions and progressively building the sorted output. Understanding each step of this process is crucial to grasping how the algorithm achieves its sorting objective.
Initialize the Array Partitions
The algorithm begins by conceptually dividing the array into two regions: a sorted portion (initially empty) on the left and an unsorted portion (initially the entire array) on the right. The boundary between these regions starts at the beginning of the array and moves rightward with each iteration.
Find the Minimum Element
In each iteration, the algorithm scans through the entire unsorted portion to locate the minimum element. This is done by maintaining a variable that tracks the index of the smallest element found so far. The algorithm compares each element in the unsorted region with the current minimum, updating the minimum index whenever a smaller element is discovered. This linear search through the unsorted portion is what contributes to the algorithm's O(n²) time complexity.
Swap to the Correct Position
Once the minimum element is identified, it is swapped with the first element of the unsorted portion (which is the element immediately after the sorted portion). This single swap operation places the minimum element in its final, correct position. Note that if the minimum element is already at the first position of the unsorted region, no swap is necessary, though the algorithm still counts this as an iteration.
Expand the Sorted Region
After the swap, the boundary between the sorted and unsorted portions advances one position to the right. The element that was just placed is now considered part of the sorted region and will never be examined again. This means the sorted portion grows by one element while the unsorted portion shrinks by one element with each iteration.
Repeat Until Completion
Steps 2 through 4 are repeated until the unsorted portion contains only one element (or is empty). At this point, the last remaining element must be in its correct position, as all smaller elements have already been placed in the sorted portion. The algorithm requires exactly n-1 passes for an array of n elements, since the last element is automatically in place when n-1 elements have been sorted.
Step-by-Step Example
Consider sorting the array [64, 25, 12, 22, 11]:
- Initial:
[64, 25, 12, 22, 11]- Entire array is unsorted - Pass 1: Find minimum (11), swap with first →
[11, 25, 12, 22, 64] - Pass 2: Find minimum (12), swap with first unsorted →
[11, 12, 25, 22, 64] - Pass 3: Find minimum (22), swap with first unsorted →
[11, 12, 22, 25, 64] - Pass 4: Find minimum (25), already in position →
[11, 12, 22, 25, 64] - Complete: Last element (64) is automatically in place
Notice how each pass guarantees one more element is in its final sorted position, building the solution incrementally from left to right.
Visualization
Click Start to begin visualization
Implementation
def selection_sort(arr):
n = len(arr)
# Traverse through all array elements
for i in range(n):
# Find the minimum element in remaining unsorted array
min_idx = i
for j in range(i + 1, n):
if arr[j] < arr[min_idx]:
min_idx = j
# Swap the found minimum element with the first element
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr
# Usage example
if __name__ == "__main__":
arr = [64, 34, 25, 12, 22, 11, 90]
print("Original array:", arr)
selection_sort(arr)
print("Sorted array:", arr)
#include <iostream>
#include <vector>
class SelectionSort {
public:
static void sort(std::vector<int>& arr) {
int n = arr.size();
// One by one move boundary of unsorted subarray
for (int i = 0; i < n - 1; i++) {
// Find the minimum element in unsorted array
int min_idx = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[min_idx]) {
min_idx = j;
}
}
// Swap the found minimum element with the first element
if (min_idx != i) {
std::swap(arr[min_idx], arr[i]);
}
}
}
};
// Usage example
int main() {
std::vector<int> arr = {64, 34, 25, 12, 22, 11, 90};
std::cout << "Original array: ";
for (int num : arr) std::cout << num << " ";
std::cout << std::endl;
SelectionSort::sort(arr);
std::cout << "Sorted array: ";
for (int num : arr) std::cout << num << " ";
std::cout << std::endl;
return 0;
}
public class SelectionSort
{
public static void Sort(int[] arr)
{
int n = arr.Length;
// One by one move boundary of unsorted subarray
for (int i = 0; i < n - 1; i++)
{
// Find the minimum element in unsorted array
int min_idx = i;
for (int j = i + 1; j < n; j++)
{
if (arr[j] < arr[min_idx])
{
min_idx = j;
}
}
// Swap the found minimum element with the first element
if (min_idx != i)
{
(arr[min_idx], arr[i]) = (arr[i], arr[min_idx]);
}
}
}
// Usage example
public static void Main(string[] args)
{
int[] arr = { 64, 34, 25, 12, 22, 11, 90 };
Console.WriteLine("Original array: " + string.Join(" ", arr));
Sort(arr);
Console.WriteLine("Sorted array: " + string.Join(" ", arr));
}
}
Complexity Analysis
| Case | Time Complexity |
|---|---|
| Best | O(n²) |
| Average | O(n²) |
| Worst | O(n²) |
Advantages and Disadvantages
Advantages
- Simple and easy to understand
- Performs well on small arrays
- In-place algorithm - requires no extra space
- Minimal number of swaps (O(n) swaps)
Disadvantages
- O(n²) complexity makes it inefficient for large lists
- Not stable - does not preserve the relative order of equal elements
- Does not adapt to the data in any way