Сортировка вставками - Алгоритмика
Сортировка вставками

Сортировка вставками

Пусть на kk-ом шаге у нас уже отсортирован префикс длины kk. Чтобы увеличить этот отсортированный префикс, мы можем взять элемент, следующий после него, и менять его с левым соседом, пока этот элемент не окажется больше своего левого соседа. Когда это произойдет, это будет означать, что он будет больше всех элементов слева и меньше всех элементов префикса справа, и значит мы правильно вставили этот элемент в отсортированную часть массива.

void insertion_sort(int *a, int n) {
    for (int k = 1; k < n; k++)
        for (int i = k; i > 0 && a[i - 1] < a[i]; i--)
            // мы ещё не дошли до начала массива и предыдущий элемент меньше
            swap(a[i], a[i - 1]);
}

Время работы в худшем случае тоже квадратичное — например, когда массив упорядочен по убыванию.

Однако, в отличие от двух предыдущих квадратичных сортировок, в некоторых хороших случаях время работы может быть меньше, потому что мы добавили условие ранней остановки во внутреннем цикле. Например, алгоритм сделает O(n)O(n) операций, если массив изначально отсортирован.

Упражнение. Покажите, что алгоритм делает O(nk)O(n k) операций, если массив «почти отсортирован» в том смысле, что каждый элемент находится на расстоянии не более kk от его позиции в отсортированном массиве.