Сортировка методом Шелла
Сортировка Шелла это, по сути, модификация схем сортировки других алгоритмов. Фактически для сортировки элементов используются другие алгоритмы, такие как: пузырьком, вставками, выбором и т.д. Но только эти алгоритмы применяются не ко всей исходной последовательности, а к ее частям.
Алгоритм:
Сначала в исходной последовательности сортируются между собой элементы, отстоящие друг от друга на расстоянии n/2 элементов, затем на расстоянии n/4 и т.д. до тех пор пока не получим 2 последовательности, элементы которых отстоят друг от друга на расстоянии 1-го элемента. После этого делаем сортировку этой полученной последовательности выбранным методом и на выходе имеем уже полностью отсортированную последовательность.
Пример
Пример. Имеется последовательность [2, 3, 9, 2, 8, 4, 6, 8, 11, 12, 4, 6], n=12. Символом d - будем обозначать расстояние между сортируемыми элементами на каждом шаге (на первом шаге d = n/2, на втором d = d/2 и т.д.)
1 шаг. d = n/2 = 6. => Получаем 6 сортируемых групп(имеют одинаковый цвет): [2, 3, 9, 2, 8, 4, 6, 8, 11, 12, 4, 6] После сортировки в пределах каждой группы, имеем: [2, 3, 9, 2, 4, 4, 6, 8, 11, 12, 8, 6]
2 шаг. d = d/2 = 3. => Получаем 2 сортируемых группы(имеют одинаковый цвет): [2, 3, 9, 2, 4, 4, 6, 8, 11, 12, 8, 6] После сортировки в пределах каждой группы, имеем: [2, 3, 4, 2, 4, 6, 6, 8, 9, 12, 8, 11]
3 шаг. d = d/2 = 1(целочисленное деление) => заключительный шаг. Сортируем всю последовательность: [2, 3, 4, 2, 4, 6, 6, 8, 9, 12, 8, 11] в итоге получим: [2, 2, 3, 4, 4, 6, 6, 8, 8, 9, 11, 12]
Сортировка Хоара(QuickSort)
QuickSort является существенно улучшенным вариантом алгоритма сортировки с помощью прямого обмена (его варианты известны как «Пузырьковая сортировка» и «Шейкерная сортировка»), известного, в том числе, своей низкой эффективностью. Принципиальное отличие состоит в том, что после каждого прохода элементы делятся на две независимые группы. Любопытный факт: улучшение самого неэффективного прямого метода сортировки дало в результате эффективный улучшенный метод.
Даёт в среднем O(n log n) обменов при упорядочении n элементов. В реальности именно такая ситуация обычно имеет место при случайном порядке элементов и выборе опорного элемента из середины массива либо случайно.
На практике (в случае, когда обмены являются более затратной операцией, чем сравнения) быстрая сортировка значительно быстрее, чем другие алгоритмы с оценкой O(n lg n), по причине того, что внутренний цикл алгоритма может быть эффективно реализован почти на любой архитектуре
Алгоритм
Быстрая сортировка использует стратегию «разделяй и властвуй». Шаги алгоритма таковы:
Выбираем в массиве некоторый элемент, который будем называть опорным элементом. С точки зрения корректности алгоритма выбор опорного элемента безразличен. С точки зрения повышения эффективности алгоритма выбираться должна медиана, но без дополнительных сведений о сортируемых данных её обычно невозможно получить. Известные стратегии: выбирать постоянно один и тот же элемент, например, средний или последний по положению; выбирать элемент со случайно выбранным индексом.
Операция разделения массива: реорганизуем массив таким образом, чтобы все элементы, меньшие или равные опорному элементу, оказались слева от него, а все элементы, большие опорного — справа от него. Обычный алгоритм операции:
Два индекса — l и r, приравниваются к минимальному и максимальному индексу разделяемого массива соответственно.
Вычисляется индекс опорного элемента m.
Индекс l последовательно увеличивается до тех пор, пока l-й элемент не превысит опорный.
Индекс r последовательно уменьшается до тех пор, пока r-й элемент не окажется меньше либо равен опорному.
Если r = l — найдена середина массива — операция разделения закончена, оба индекса указывают на опорный элемент.
Если l < r — найденную пару элементов нужно обменять местами и продолжить операцию разделения с тех значений l и r, которые были достигнуты. Следует учесть, что если какая-либо граница (l или r) дошла до опорного элемента, то при обмене значение m изменяется на r-й или l-й элемент соответственно.
Рекурсивно упорядочиваем подмассивы, лежащие слева и справа от опорного элемента.
Базой рекурсии являются наборы, состоящие из одного или двух элементов. Первый возвращается в исходном виде, во втором, при необходимости, сортировка сводится к перестановке двух элементов. Все такие отрезки уже упорядочены в процессе разделения.
Поскольку в каждой итерации (на каждом следующем уровне рекурсии) длина обрабатываемого отрезка массива уменьшается, по меньшей мере, на единицу, терминальная ветвь рекурсии будет достигнута всегда и обработка гарантированно завершится.
Пример:
Пример. Пусть исходный набор включает 11 чисел: 13 42 28 17 9 25 47 31 39 15 20. Основные шаги сортировки:
Выбор серединного элемента 25 (индекс 6): 13 42 28 17 9 25 47 31 39 15 20
поиск слева первого элемента, большего 25: 42 (2 сравнения)
поиск справа от конца первого элемента, меньшего 25: 20 (1 сравнение)
перестановка элементов 42 и 20: 13 20 28 17 9 25 47 31 39 15 42
поиск слева от 25 еще одного элемента, большего 25: 28 (1 сравнение)
поиск справа от 25 еще одного элемента, меньшего 25: 15 (1 сравнение)
перестановка элементов 28 и 15: 13 20 15 17 9 25 47 31 39 28 42
поиск слева от 25 еще одного элемента, большего 25: нет (2 сравнения)
поиск справа от 25 еще одного элемента, меньшего 25: нет (3 сравнения)
теперь слева от 25 все элементы меньше 25, а справа – больше
выделяем отдельно левую часть: 13 20 15 17 9
выбираем серединный элемент 15 (индекс 3): 13 20 15 17 9
поиск слева от 15 элемента, большего 15: 20 (2 сравнения)
поиск справа от 15 элемента, меньшего 15: 9 (1 сравнение)
перестановка 20 и 9: 13 9 15 17 20
поиск справа от 15 еще одного элемента, меньшего 15: нет (1 сравнение)
теперь слева от 15 все элементы меньше 15, а справа – больше
поскольку слева от 15 только 2 элемента, просто сравниваем их друг с другом и переставляем (9 и 13)
поскольку справа от 15 только 2 элемента, просто сравниваем их и не переставляем
получаем для левой части упорядоченный набор: 9 13 15 17 20
возвращаемся к правой части: 47 31 39 28 42
выделяем серединный элемент 39 (индекс в данном поднаборе – 3): 47 31 39 28 42
поиск слева от 39 элемента, большего 39: 47 (1 сравнение)
поиск справа от 39 элемента, меньшего 39: 28 (2 сравнения)
переставляем 47 и 28: 28 31 39 47 42
поиск слева от 39 еще одного элемента, большего 39: нет (1 сравнение)
теперь слева от 39 все элементы меньше 39, а справа – больше
поскольку слева от 39 только 2 элемента, просто сравниваем их и не переставляем
поскольку справа от 39 только 2 элемента, просто сравниваем их и переставляем (42 и 47)
получаем для правой части упорядоченный набор: 28 31 39 42 47
вместе с левой частью и серединным элементом 25 получаем окончательный результат
Итого для данного примера потребовалось 22 сравнения и 6 пересылок.
