Сортировки: пузырёк, вставки, быстрая, слиянием

Пять классических сортировок с кодом, таблицей сложностей и объяснением, какую выбрать в лабораторной и что ответить про устойчивость.

В лабораторной обычно требуют реализовать две-три сортировки и сравнить их по времени на массивах разного размера. Ниже — минимальные корректные реализации и то, что нужно сказать про каждую.

Пузырьковая — O(n²)

def bubble(a):
    n = len(a)
    for i in range(n - 1):
        swapped = False
        for j in range(n - 1 - i):
            if a[j] > a[j + 1]:
                a[j], a[j + 1] = a[j + 1], a[j]
                swapped = True
        if not swapped:      # массив уже отсортирован
            break
    return a

Флаг swapped даёт лучший случай O(n) на почти отсортированных данных — это тот нюанс, который отличает «реализовал» от «понимаю».

Вставками — O(n²), но быстрая на практике

def insertion(a):
    for i in range(1, len(a)):
        key, j = a[i], i - 1
        while j >= 0 and a[j] > key:
            a[j + 1] = a[j]
            j -= 1
        a[j + 1] = key
    return a

На массивах до ~50 элементов обгоняет быструю сортировку из-за малых констант, поэтому промышленные сортировки переключаются на неё для коротких подмассивов.

Быстрая (quicksort) — O(n log n) в среднем

def quicksort(a):
    if len(a) <= 1:
        return a
    pivot = a[len(a) // 2]
    left  = [x for x in a if x < pivot]
    mid   = [x for x in a if x == pivot]
    right = [x for x in a if x > pivot]
    return quicksort(left) + mid + quicksort(right)
Эта версия наглядна, но тратит O(n) памяти. Классический вариант с разбиением Хоара сортирует на месте — если в методичке требуют «без дополнительной памяти», нужен именно он.

Слиянием (merge sort) — гарантированные O(n log n)

def merge_sort(a):
    if len(a) <= 1:
        return a
    m = len(a) // 2
    l, r = merge_sort(a[:m]), merge_sort(a[m:])
    res, i, j = [], 0, 0
    while i < len(l) and j < len(r):
        if l[i] <= r[j]:
            res.append(l[i]); i += 1
        else:
            res.append(r[j]); j += 1
    return res + l[i:] + r[j:]

Сравнительная таблица

АлгоритмЛучшийСреднийХудшийПамятьУстойчивая
ПузырёкO(n)O(n²)O(n²)O(1)да
ВыборомO(n²)O(n²)O(n²)O(1)нет
ВставкамиO(n)O(n²)O(n²)O(1)да
БыстраяO(n log n)O(n log n)O(n²)O(log n)нет
СлияниемO(n log n)O(n log n)O(n log n)O(n)да
ПирамидальнаяO(n log n)O(n log n)O(n log n)O(1)нет

Что такое устойчивость и зачем она

Устойчивая сортировка сохраняет исходный порядок равных элементов. Это важно при многоуровневой сортировке: отсортировали список студентов по имени, затем устойчиво по группе — внутри каждой группы имена остались упорядоченными.

Частые вопросы

Какую сортировку выбрать для лабораторной по сравнению времени?

Возьмите пузырёк (медленный, наглядный), вставками (O(n²), но быстрый) и быструю. Разница на n = 10 000 будет видна невооружённым глазом.

Можно ли сортировать быстрее, чем за O(n log n)?

Сравнением — нет, это доказанная нижняя граница. Но подсчётом (counting sort) или поразрядно (radix sort) можно за O(n), если у ключей ограниченный диапазон.

Читайте также

Сделаем работу по этой теме

Опишите задачу — ответим в течение 15 минут в личных сообщениях ВКонтакте, назовём срок и цену. Предоплаты за оценку нет.

  • Оценка заявки бесплатно
  • Правки по замечаниям преподавателя
  • Работы по всем техническим и IT-дисциплинам

Нажимая кнопку, вы соглашаетесь на обработку указанных данных для ответа на заявку.