Получить доступ

Что такое устойчивая (стабильная) сортировка и когда это важно?

JuniorСортировки
Ещё спрашивают так:
  • Какие сортировки устойчивы?
  • Как отсортировать по двум полям?
Коротко

Устойчивая сортировка сохраняет исходный порядок элементов с равными ключами.

  • Устойчивы: вставками, пузырьком, слиянием, Timsort, сортировка подсчётом; неустойчивы: быстрая, пирамидальная, выбором
  • Важно для сортировки по нескольким полям последовательными проходами и для предсказуемого интерфейса

А ещё Сортировка по двум полям: сначала по второстепенному, затем устойчиво по главному

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Попробуйте сами

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

Подробно

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

Когда это важно:

  • сортировка по нескольким ключам по очереди. Нужно упорядочить сотрудников по отделу, а внутри отдела — по фамилии. Можно отсортировать по фамилии, а затем устойчиво по отделу: порядок фамилий внутри отдела сохранится;
  • предсказуемый интерфейс. Пользователь кликает по столбцу таблицы — строки с одинаковым значением не должны «прыгать»;
  • сортировка записей, у которых есть естественный порядок (по времени поступления).

Устойчивы: вставками, пузырьком, слиянием, Timsort (sorted в Python, Collections.sort и сортировка объектов в Java), подсчётом, поразрядная. Неустойчивы: быстрая, пирамидальная, выбором; Arrays.sort для примитивов в Java — но для чисел устойчивость и не имеет смысла.

Неустойчивый алгоритм можно сделать устойчивым, добавив к ключу исходный индекс — ценой памяти. Но проще сортировать по составному ключу сразу: key=lambda e: (e.dept, e.last_name).

Пример

people = [("Иванов", "продажи"), ("Петров", "ИТ"), ("Сидоров", "продажи"), ("Абрамов", "ИТ")]

by_name = sorted(people, key=lambda p: p[0])
by_dept = sorted(by_name, key=lambda p: p[1])   # устойчиво: внутри отдела — по фамилии
# [('Абрамов', 'ИТ'), ('Петров', 'ИТ'), ('Иванов', 'продажи'), ('Сидоров', 'продажи')]

sorted(people, key=lambda p: (p[1], p[0]))      # то же одним проходом

Что хотят услышать

  • Определение через порядок равных элементов.
  • Какие алгоритмы устойчивы, а какие нет.
  • Практический пример: сортировка по нескольким полям.

Частые ошибки

  • Путать устойчивость с «надёжностью» или скоростью алгоритма.
  • Считать быструю сортировку устойчивой.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем