Selection & Insertion Sort
Written and reviewed by Gagan Bhardwaj · Senior IT Faculty · 15+ years’ experience
Selection Sort vs Insertion Sort
Both algorithms grow a sorted prefix and use O(1) auxiliary space, but their work is different. Selection sort searches the unsorted suffix for its minimum and swaps it into the next slot. Insertion sort removes the next key conceptually, shifts larger prefix elements right, and inserts the key into the gap.
| Question | Selection sort | Insertion sort |
|---|---|---|
| Main operation | Select minimum + swap | Compare + shift + insert |
| Nearly sorted input | Still Θ(n²) comparisons | Can approach Θ(n) |
| Writes | O(n) swaps | Up to Θ(n²) moves |
| Typical stability | Not stable | Stable |
For general production sorting, prefer the standard algorithms library.
Selection Sort Algorithm and Trace
Invariant: before outer index i, the prefix [0,i) contains the smallest i values in final order. Find the minimum index in [i,n) and exchange it with position i.
| Pass | Unsorted range | Selected | After pass |
|---|---|---|---|
| 0 | 29 10 14 37 13 | 10 | 10 | 29 14 37 13 |
| 1 | 29 14 37 13 | 13 | 10 13 | 14 37 29 |
| 2 | 14 37 29 | 14 | 10 13 14 | 37 29 |
| 3 | 37 29 | 29 | 10 13 14 29 37 |
Complete Selection Sort Function
void selection_sort(std::vector<int>& values) {
for (std::size_t i = 0; i < values.size(); ++i) {
std::size_t minimum = i;
for (std::size_t j = i + 1; j < values.size(); ++j) {
if (values[j] < values[minimum]) minimum = j;
}
if (minimum != i) std::swap(values[i], values[minimum]);
}
}Checking minimum != i avoids a self-swap. Comparisons remain quadratic regardless of initial order. The distant swap can move an equal-key record past another, so this ordinary version is not stable.
Insertion Sort Algorithm and Trace
Invariant: before processing index i, prefix [0,i) is sorted and contains the original prefix values. Save the key, shift every larger predecessor one place right, and write the key into the open slot.
| Key | Action | After insertion |
|---|---|---|
| 10 | Shift 29 | 10 29 | 14 37 13 |
| 14 | Shift 29 | 10 14 29 | 37 13 |
| 37 | No shift | 10 14 29 37 | 13 |
| 13 | Shift 37,29,14 | 10 13 14 29 37 |
The scan stops as soon as the predecessor is not greater than the key. This early stopping makes insertion sort adaptive.
Complete, Safe C++ Program and Output
#include <iostream>
#include <utility>
#include <vector>
void selection_sort(std::vector<int>& values) {
for (std::size_t i = 0; i < values.size(); ++i) {
std::size_t minimum = i;
for (std::size_t j = i + 1; j < values.size(); ++j)
if (values[j] < values[minimum]) minimum = j;
if (minimum != i) std::swap(values[i], values[minimum]);
}
}
void insertion_sort(std::vector<int>& values) {
for (std::size_t i = 1; i < values.size(); ++i) {
const int key = values[i];
std::size_t j = i;
while (j > 0 && values[j - 1] > key) {
values[j] = values[j - 1];
--j;
}
values[j] = key;
}
}
void print(const char* label, const std::vector<int>& values) {
std::cout << label << ':';
for (int value : values) std::cout << ' ' << value;
std::cout << '\n';
}
int main() {
std::vector<int> selection{29, 10, 14, 37, 13};
std::vector<int> insertion = selection;
selection_sort(selection);
insertion_sort(insertion);
print("Selection", selection);
print("Insertion", insertion);
}j > 0 is evaluated before values[j-1], preventing unsigned underflow. The two algorithms receive identical data for a fair comparison.
Complexity, Stability and Data Movement
| Property | Selection | Insertion |
|---|---|---|
| Best time | Θ(n²) | Θ(n) |
| Average time | Θ(n²) | Θ(n²) |
| Worst time | Θ(n²) | Θ(n²) |
| Auxiliary space | O(1) | O(1) |
| Stable as written | No | Yes |
| Adaptive | No | Yes |
| Writes/moves | O(n) swaps | Up to Θ(n²) shifts |
A swap may represent several assignments, so measure the actual value type and storage medium before using “fewer swaps” as a performance conclusion.
Decision Guide
- Nearly sorted or small: insertion sort often performs well and is commonly used as a small-partition component inside advanced sorting implementations.
- Writes are unusually expensive: selection sort limits the number of swaps, though comparisons remain quadratic.
- Large general range: use
std::sort. - Stable library result: use
std::stable_sort. - Predictable Θ(n log n) study: learn merge sort.
Algorithm selection depends on size, current order, stability, memory, comparison cost and movement cost—not on one complexity cell alone.
Common Mistakes, Tests and Practice
| Mistake | Correction |
|---|---|
| Swapping on every inner selection comparison | Find minimum, then swap once |
| Overwriting insertion key | Save key before shifts |
| Accessing index -1 | Check j > 0 first |
Using >= while shifting | Use strict > for stability |
| Calling selection adaptive | It scans remaining suffix every pass |
Test empty, one item, sorted, reverse, equal, duplicates and negative values. Practice descending comparators, record stability, comparison/move counters and binary-insertion search (noting that shifts still cost linear time).
Authoritative References
Definitions, growth rates and stability properties were checked against these references. Compare one more quadratic method in bubble sort.
Frequently Asked Questions
What is the main difference between selection and insertion sort?
Which is faster on nearly sorted data?
Which algorithm performs fewer writes?
Are selection sort and insertion sort stable?
Do these algorithms need extra arrays?
Selection vs Insertion Sort
दोनों sorted prefix बढ़ाते और O(1) extra space लेते हैं। Selection unsorted suffix से minimum चुनकर next slot में swap करता है। Insertion next key को save करके larger prefix elements shift करता और gap में key डालता है।
| Point | Selection | Insertion |
|---|---|---|
| Nearly sorted | Θ(n²) comparisons | Θ(n) तक |
| Writes | O(n) swaps | Θ(n²) तक moves |
| Stable usual form | नहीं | हाँ |
Selection Sort Trace
हर pass में remaining range का minimum खोजें और current position से swap करें। Prefix में final smallest values आते जाते हैं।
29 10 14 37 13
10 | 29 14 37 13
10 13 | 14 37 29
10 13 14 | 37 29
10 13 14 29 37Selection Program
for (std::size_t i=0; i<values.size(); ++i) {
std::size_t minimum=i;
for (std::size_t j=i+1; j<values.size(); ++j)
if (values[j]<values[minimum]) minimum=j;
if (minimum!=i) std::swap(values[i],values[minimum]);
}Minimum पूरा खोजने के बाद एक swap करें। Distant swap equal records का order बदल सकता है।
Insertion Sort Trace
Key save करें, उससे बड़े predecessors right shift करें और empty position में key लिखें।
29 10 14 37 13
10 29 | 14 37 13
10 14 29 | 37 13
10 14 29 37 | 13
10 13 14 29 37Insertion Program
for (std::size_t i=1; i<values.size(); ++i) {
int key=values[i];
std::size_t j=i;
while (j>0 && values[j-1]>key) {
values[j]=values[j-1];
--j;
}
values[j]=key;
}j>0 पहले check होने से unsigned index underflow नहीं होता।
Complexity और Stability
| Property | Selection | Insertion |
|---|---|---|
| Best | Θ(n²) | Θ(n) |
| Average/Worst | Θ(n²) | Θ(n²) |
| Space | O(1) | O(1) |
| Stable | नहीं | हाँ, strict > |
| Adaptive | नहीं | हाँ |
Decision Guide
- Nearly sorted/small data: insertion अच्छा candidate।
- Writes बहुत expensive: selection के limited swaps उपयोगी हो सकते हैं।
- Large general range:
std::sort। - Stable library result:
std::stable_sort। - Θ(n log n) study: merge sort।
STL algorithms production choice समझाता है।
Mistakes, Tests और Practice
- Selection inner loop में बार-बार swap न करें।
- Insertion shifts से पहले key save करें।
j>0check पहले रखें।- Stability के लिए shift condition strict
>हो।
Empty, sorted, reverse, duplicate और negative inputs test करें; comparisons और moves count करें।
Authoritative संदर्भ
Definitions और complexity sources से verify किए गए हैं। Bubble sort भी compare करें।