Сортировка вставками
Последнее обновление
Сортировка вставками строит отсортированный массив по одному элементу за раз. Она берёт следующий неотсортированный элемент («ключ») и сдвигает каждый больший элемент в отсортированной области на одну позицию вправо, затем помещает ключ в освободившийся промежуток. Именно так большинство людей сортируют карты в руке. Нажмите «воспроизвести» выше, чтобы увидеть, как вставляется каждый ключ, или пройдите сдвиги по одному.
Сортировка вставками очень быстра на малых или почти отсортированных входных данных - она работает за O(n), когда данные уже отсортированы, - поэтому многие гибридные сортировки прибегают к ней для небольших подмассивов.
Временная и пространственная сложность
| Случай | Сложность | Примечания |
|---|---|---|
| Лучший случай | O(n) | Уже отсортировано |
| Средний случай | O(n²) | Случайный порядок |
| Худший случай | O(n²) | Обратный порядок |
| Память | O(1) | На месте |
| Устойчивая | Да | Равные элементы сохраняют относительный порядок |
Пошагово
| Шаг | Что происходит |
|---|---|
| 1 | Считайте первый элемент отсортированной областью размера один. |
| 2 | Возьмите следующий элемент в качестве ключа. |
| 3 | Сдвиньте каждый отсортированный элемент, больший ключа, на одну позицию вправо. |
| 4 | Вставьте ключ в открывшийся промежуток. |
| 5 | Повторяйте, пока не будут вставлены все элементы. |
Разобранный пример
Сортировка [5, 2, 4, 1]:
| Проход | Массив | Действие |
|---|---|---|
| Старт | [5, 2, 4, 1] | 5 — начальная отсортированная область размера один. |
| 1 | [2, 5, 4, 1] | Ключ 2: сдвинуть 5 вправо, вставить 2 в начало. |
| 2 | [2, 4, 5, 1] | Ключ 4: сдвинуть 5 вправо, 2 меньше, поэтому стоп, вставить 4. |
| 3 | [1, 2, 4, 5] | Ключ 1: сдвинуть 5, 4, 2 вправо, вставить 1 в начало. |
| Готово | [1, 2, 4, 5] | Все элементы вставлены; массив отсортирован. |
Когда использовать сортировку вставками
| Используйте, когда | Избегайте, когда |
|---|---|
Массив небольшой (примерно n < 20). | Массив большой и упорядочен случайно. |
Данные уже почти отсортированы, что даёт лучший случай O(n). | Нужен гарантированный худший случай O(n log n). |
Нужна устойчивая сортировка на месте с дополнительной памятью O(1). | Перемещение элементов дорого, так как выполняется много сдвигов. |
| Данные поступают постепенно и должны оставаться отсортированными в реальном времени. | Вход отсортирован в обратном порядке, её худший случай O(n²). |
Код Insertion Sort
Чистая, готовая к запуску реализация Insertion Sort на Python, JavaScript, Java, C++, C. Выберите язык, скопируйте код или откройте его уже загруженным в плейграунде Coddy.
Код Insertion Sort на Python
1def insertion_sort(a):2 for i in range(1, len(a)):3 key = a[i]4 j = i - 15 # Shift larger elements one slot to the right6 while j >= 0 and a[j] > key:7 a[j + 1] = a[j]8 j -= 19 a[j + 1] = key10 return a11
12
13nums = [7, 3, 9, 1, 5, 8, 2]14print("Before:", nums)15insertion_sort(nums)16print("After: ", nums)Код Insertion Sort на JavaScript
1function insertionSort(a) {2 for (let i = 1; i < a.length; i++) {3 const key = a[i];4 let j = i - 1;5 // Shift larger elements right to open a slot for key6 while (j >= 0 && a[j] > key) {7 a[j + 1] = a[j];8 j--;9 }10 a[j + 1] = key;11 }12 return a;13}14
15const data = [5, 2, 9, 1, 7, 3];16console.log("Before:", data);17console.log("Sorted:", insertionSort([...data]));Код Insertion Sort на Java
1import java.util.Arrays;2
3public class Main {4 static void insertionSort(int[] arr) {5 for (int i = 1; i < arr.length; i++) {6 int key = arr[i];7 int j = i - 1;8 // Shift larger elements one slot to the right9 while (j >= 0 && arr[j] > key) {10 arr[j + 1] = arr[j];11 j--;12 }13 arr[j + 1] = key;14 }15 }16
17 public static void main(String[] args) {18 int[] arr = {7, 3, 9, 1, 5, 8, 2};19 System.out.println("Before: " + Arrays.toString(arr));20 insertionSort(arr);21 System.out.println("After: " + Arrays.toString(arr));22 }23}Код Insertion Sort на C++
1#include <iostream>2#include <vector>3
4void printVec(const std::vector<int>& a) {5 for (int x : a) std::cout << x << " ";6 std::cout << "\n";7}8
9void insertionSort(std::vector<int>& a) {10 for (size_t i = 1; i < a.size(); ++i) {11 int key = a[i];12 int j = static_cast<int>(i) - 1;13 // Shift larger elements one slot to the right14 while (j >= 0 && a[j] > key) {15 a[j + 1] = a[j];16 --j;17 }18 a[j + 1] = key;19 }20}21
22int main() {23 std::vector<int> data = {7, 3, 9, 1, 5, 8, 2};24 std::cout << "Before: ";25 printVec(data);26 insertionSort(data);27 std::cout << "After: ";28 printVec(data);29 return 0;30}Код Insertion Sort на C
1#include <stdio.h>2
3void printArr(const int a[], int n) {4 for (int i = 0; i < n; i++) printf("%d ", a[i]);5 printf("\n");6}7
8void insertionSort(int a[], int n) {9 for (int i = 1; i < n; i++) {10 int key = a[i];11 int j = i - 1;12 // Shift larger elements one slot to the right13 while (j >= 0 && a[j] > key) {14 a[j + 1] = a[j];15 j--;16 }17 a[j + 1] = key;18 }19}20
21int main(void) {22 int data[] = {7, 3, 9, 1, 5, 8, 2};23 int n = sizeof(data) / sizeof(data[0]);24 printf("Before: ");25 printArr(data, n);26 insertionSort(data, n);27 printf("After: ");28 printArr(data, n);29 return 0;30}Часто задаваемые вопросы о сортировке вставками
Какова временная сложность сортировки вставками?
O(n²) в среднем и в худшем случае, но O(n) на уже отсортированном или почти отсортированном массиве. Она использует O(1) дополнительной памяти.Является ли сортировка вставками устойчивой?
Когда следует использовать сортировку вставками?
В чём разница между сортировкой вставками и сортировкой пузырьком?
O(n²), но сортировка вставками сдвигает элементы, чтобы открыть промежуток для ключа, тогда как сортировка пузырьком многократно меняет местами соседние неупорядоченные пары. Сортировка вставками обычно выполняет меньше записей и работает лучше на практике, особенно на почти отсортированных данных, где она достигает лучшего случая O(n).Почему сортировка вставками быстрее сортировки слиянием на небольших массивах?
O(n log n) несмотря на худшую асимптотическую сложность. Именно поэтому гибридные сортировки, такие как Timsort и introsort, переключаются на сортировку вставками для небольших подмассивов.Сортировка вставками работает лучше со связным списком или с массивом?
O(n²).