Сортировка вставками — различия между версиями
| Xapdkop (обсуждение | вклад)   (→Двухпутевые вставки:  Исправлена нумерация элементов (для первых четырех съехала на плюс один)) | |||
| Строка 91: | Строка 91: | ||
| !style="background-color:#EEE"| Описание шага | !style="background-color:#EEE"| Описание шага | ||
| |- | |- | ||
| − | |colspan=3|''Первый проход (проталкиваем  | + | |colspan=3|''Первый проход (проталкиваем первый элемент — '''''5''''')'' | 
| |- | |- | ||
| |style="background-color:#FFF;padding:2px 10px"|   | |style="background-color:#FFF;padding:2px 10px"|   | ||
| Строка 97: | Строка 97: | ||
| |style="background-color:#FFF;padding:2px 10px"| Так как в поле вывода нет элементов то мы просто добавляем элемент туда. | |style="background-color:#FFF;padding:2px 10px"| Так как в поле вывода нет элементов то мы просто добавляем элемент туда. | ||
| |- | |- | ||
| − | |colspan=3|''Второй проход (проталкиваем  | + | |colspan=3|''Второй проход (проталкиваем второй элемент — '''''7''''')'' | 
| |- | |- | ||
| |style="background-color:#FFF;padding:2px 30px"| 5   | |style="background-color:#FFF;padding:2px 30px"| 5   | ||
| Строка 103: | Строка 103: | ||
| |style="background-color:#FFF;padding:2px 10px"| С помощью Бинарного поиска находим позицию и так как позиция крайняя то сдвигать ничего не приходится. | |style="background-color:#FFF;padding:2px 10px"| С помощью Бинарного поиска находим позицию и так как позиция крайняя то сдвигать ничего не приходится. | ||
| |-    | |-    | ||
| − | |colspan=3|''Третий проход (проталкиваем  | + | |colspan=3|''Третий проход (проталкиваем третий — '''''3''''')'' | 
| |- | |- | ||
| |style="background-color:#FFF;padding:2px 30px"| 5 7 | |style="background-color:#FFF;padding:2px 30px"| 5 7 | ||
| Строка 109: | Строка 109: | ||
| |style="background-color:#FFF;padding:2px 10px"| С помощью Бинарного поиска находим позицию и так как позиция крайняя то сдвигать ничего не приходится. | |style="background-color:#FFF;padding:2px 10px"| С помощью Бинарного поиска находим позицию и так как позиция крайняя то сдвигать ничего не приходится. | ||
| |- | |- | ||
| − | |colspan=3|''Четвертый проход (проталкиваем  | + | |colspan=3|''Четвертый проход (проталкиваем четвертый элемент — '''''4''''')'' | 
| |- | |- | ||
| |style="background-color:#FFF;padding:2px 20px"| 3 5 7 | |style="background-color:#FFF;padding:2px 20px"| 3 5 7 | ||
Версия 15:05, 24 февраля 2019
Сортировка вставками (англ. Insertion sort) — квадратичный алгоритм сортировки.
Содержание
Алгоритм
Задача заключается в следующем: есть часть массива, которая уже отсортирована, и требуется вставить остальные элементы массива в отсортированную часть, сохранив при этом упорядоченность. Для этого на каждом шаге алгоритма мы выбираем один из элементов входных данных и вставляем его на нужную позицию в уже отсортированной части массива, до тех пор пока весь набор входных данных не будет отсортирован. Метод выбора очередного элемента из исходного массива произволен, однако обычно (и с целью получения устойчивого алгоритма сортировки), элементы вставляются по порядку их появления во входном массиве.
Так как в процессе работы алгоритма могут меняться местами только соседние элементы, каждый обмен уменьшает число инверсий на единицу. Следовательно, количество обменов равно количеству инверсий в исходном массиве вне зависимости от реализации сортировки. Максимальное количество инверсий содержится в массиве, элементы которого отсортированы по невозрастанию. Число инверсий в таком массиве .
Алгоритм работает за , где — число обменов элементов входного массива, равное числу инверсий. В среднем и в худшем случае — за . Минимальные оценки встречаются в случае уже упорядоченной исходной последовательности элементов, наихудшие — когда они расположены в обратном порядке.
Псевдокод
function insertionSort(a):
  for i = 1 to n - 1
    j = i - 1
    while j  0 and a[j] > a[j + 1] 
      swap(a[j], a[j + 1])
      j--
Пример работы
Пример работы алгоритма для массива
| До | После | Описание шага | 
|---|---|---|
| Первый проход (проталкиваем второй элемент — 2) | ||
| 5 2 4 3 1 | 2 5 4 3 1 | Алгоритм сравнивает второй элемент с первым и меняет их местами. | 
| Второй проход (проталкиваем третий элемент — 4) | ||
| 2 5 4 3 1 | 2 4 5 3 1 | Сравнивает третий со вторым и меняет местами | 
| 2 4 5 3 1 | 2 4 5 3 1 | Второй и первый отсортированы, swap не требуется | 
| Третий проход (проталкиваем четвертый — 3) | ||
| 2 4 5 3 1 | 2 4 3 5 1 | Меняет четвертый и третий местами | 
| 2 4 3 5 1 | 2 3 4 5 1 | Меняет третий и второй местами | 
| 2 3 4 5 1 | 2 3 4 5 1 | Второй и первый отсортированы, swap не требуется | 
| Четвертый проход (проталкиваем пятый элемент — 1) | ||
| 2 3 4 5 1 | 2 3 4 1 5 | Меняет пятый и четвертый местами | 
| 2 3 4 1 5 | 2 3 1 4 5 | Меняет четвертый и третий местами | 
| 2 3 1 4 5 | 2 1 3 4 5 | Меняет третий и второй местами | 
| 2 1 3 4 5 | 1 2 3 4 5 | Меняет второй и первый местами. Массив отсортирован. | 
Оптимизации
Бинарные вставки
Теперь вместо линейного поиска позиции мы будем использовать бинарный поиск, следовательно количество сравнений изменится с до . Количество сравнений заметно уменьшилось, но для того, чтобы поставить элемент на на своё место, всё ещё необходимо переместить большое количество элементов. В итоге время выполнения алгоритма в асимптотически не уменьшилось. Бинарные вставки выгодно использовать только в случае когда сравнение занимает много времени по сравнению со сдвигом. Например когда мы используем массив длинных чисел.
function insertionSort(a):
  for i = 1 to n - 1
    j = i - 1
    k = binSearch(a, a[i], 0, j)
    for m = j downto k
      swap(a[m], a[m+1])
Двухпутевые вставки
Суть этого метода в том, что вместо отсортированной части массива мы используем область вывода. Первый элемент помещается в середину области вывода, а место для последующих элементов освобождается путём сдвига элементов влево или вправо туда, куда выгоднее. Пример для набора элементов
| До | После | Описание шага | 
|---|---|---|
| Первый проход (проталкиваем первый элемент — 5) | ||
| 5 | Так как в поле вывода нет элементов то мы просто добавляем элемент туда. | |
| Второй проход (проталкиваем второй элемент — 7) | ||
| 5 | 5 7 | С помощью Бинарного поиска находим позицию и так как позиция крайняя то сдвигать ничего не приходится. | 
| Третий проход (проталкиваем третий — 3) | ||
| 5 7 | 3 5 7 | С помощью Бинарного поиска находим позицию и так как позиция крайняя то сдвигать ничего не приходится. | 
| Четвертый проход (проталкиваем четвертый элемент — 4) | ||
| 3 5 7 | 3 4 5 7 | С помощью Бинарного поиска находим позицию. Расстояние до левого края зоны вывода меньше ем до правого то сдвигаем левую часть. | 
| Четвертый проход (проталкиваем пятый элемент — 6) | ||
| 3 4 5 7 | 3 4 5 6 7 | Расстояние до правого края меньше чем до левого, следовательно двигаем правую часть. | 
Как можно заметить структура поля вывода имеет сходство с деком, а именно мы выбираем край к которому ближе наш элемент, затем добавляем с этой стороны наш элемент и двигаем его. Как мы видим в этом примере понадобилось сдвинуть всего элемента. Благодаря тому что для вставки -ого элемента потребуется сдвигов в худшем случае вместо , то и итоговое число необходимых операций в худшем случае составит .
См. также
- Сортировка пузырьком
- Сортировка выбором
- Сортировка кучей
- Сортировка слиянием
- Быстрая сортировка
- Сортировка подсчетом
- Сортировка Шелла
Источники информации
- Сортировка вставками
- Н. Вирт Алгоритмы и структуры данных — Невский Диалект, 2008. — 352 с. — ISBN 978-5-7940-0065-8
- Визуализатор квадратичных алгоритмов
- Презентация «Сортировка вектора - 3. Insertion Sort»
