2.2.1.8 — гибрид, спроектированный под данные реального мира, а не под худший случай2.2.1.8 — a hybrid designed for real-world data, not the worst case
Находит уже отсортированные "прогоны" (runs) в реальных данных и сливает их merge sort'ом — стабильна и на практике часто ближе к O(n), чем к O(n log n), потому что настоящие данные почти никогда не бывают случайными.Finds already-sorted "runs" in real-world data and merges them with merge sort — stable, and in practice often closer to O(n) than O(n log n), because real data is almost never truly random.
Merge sort (2.2.1.5) всегда делит массив пополам вслепую, независимо от содержимого. Timsort вместо этого сначала сканирует массив и находит runs — максимальные подряд идущие участки, уже отсортированные по возрастанию или по убыванию (убывающие переворачиваются за O(длина run) — тоже дёшево). Реальные данные (частично отсортированные логи, объединённые источники, повторные вставки в почти готовую структуру) почти всегда содержат длинные runs — и чем они длиннее, тем меньше слияний нужно сделать, тем ближе итоговое время к O(n).Merge sort (2.2.1.5) always splits the array blindly in half, regardless of content. Timsort instead first scans the array and finds runs — maximal contiguous stretches already sorted ascending or descending (descending ones get reversed in O(run length) — also cheap). Real-world data (partially sorted logs, merged sources, repeated inserts into an already-mostly-built structure) almost always contains long runs — and the longer they are, the fewer merges are needed, and the closer the total time gets to O(n).
чем длиннее естественные runs во входных данных, тем меньше уровней слияния требуетсяthe longer the input's natural runs, the fewer merge levels are needed
Если run короче некоторого минимума (в реализации CPython — обычно 32-64 элемента, в зависимости от размера массива), его дополняют элементами и досортировывают insertion sort'ом (2.2.1.1) до минимальной длины — на таком маленьком масштабе insertion sort быстрее, чем создание отдельного крошечного run для слияния. Затем найденные runs сливаются попарно тем же алгоритмом слияния, что и в merge sort, с эвристикой galloping mode: если один run стабильно "проигрывает" много элементов подряд другому, слияние временно переключается на бинарный поиск позиции вставки вместо поэлементного сравнения.If a run is shorter than some minimum (in CPython's implementation, usually 32-64 elements depending on array size), it's padded with more elements and sorted up to that length with insertion sort (2.2.1.1) — at that small a scale, insertion sort is faster than creating a separate tiny run to merge. The found runs are then merged pairwise with the same merge algorithm as merge sort, with a galloping mode heuristic: if one run consistently "loses" many elements in a row to the other, the merge temporarily switches to a binary search for the insertion point instead of element-by-element comparison.
Здесь минимальная длина run — 4 элемента (вместо 32-64 у настоящего CPython, чтобы эффект был виден на маленьком массиве). Фаза 1 — найти естественные runs (зелёный — возрастающий, оранжевый — убывающий с разворотом, фиолетовый — короткий run, дополненный insertion sort'ом до минимальной длины). Фаза 2 — слить найденные runs попарно, слева направо, тем же алгоритмом слияния, что в merge sort.Here the minimum run length is 4 elements (instead of CPython's real 32-64, so the effect is visible on a small array). Phase 1 — find natural runs (green — ascending, orange — descending with a reversal, purple — a short run padded up to the minimum length with insertion sort). Phase 2 — merge the found runs pairwise, left to right, with the same merge algorithm as merge sort.
нажмите «Вперёд» или «Играть», чтобы начатьpress "Forward" or "Play" to begin
Timsort был разработан Тимом Питерсом именно для CPython (отсюда название) и остаётся единственным алгоритмом сортировки списков в языке — стабильность нужна, потому что Python-объекты часто сортируются по составному ключу в несколько проходов.Timsort was developed by Tim Peters specifically for CPython (hence the name) and remains the only list-sorting algorithm in the language — stability matters because Python objects are often sorted by a composite key across several passes.
Java использует Timsort для Object[] и коллекций, но обычный IntroSort/dual-pivot quicksort — для примитивных типов int[], double[] и так далее, где стабильность не имеет смысла (примитивы неразличимы при равенстве значений).Java uses Timsort for Object[] and collections, but a plain IntroSort/dual-pivot quicksort for primitive types like int[], double[], and so on, where stability is meaningless (primitives are indistinguishable when their values are equal).
Каждый отдельный сервер пишет лог, уже отсортированный по времени; при объединении нескольких таких логов Timsort находит эти готовые runs автоматически и сливает их почти без лишней работы — ровно тот сценарий, под который алгоритм проектировался.Each individual server writes a log already sorted by time; when merging several such logs, Timsort finds these ready-made runs automatically and merges them with almost no wasted work — exactly the scenario the algorithm was designed for.