
- •1.1Алгоритмы сортировки данных
- •1.1.1Методы внутренней сортировки
- •1.1.1.1Метод выбора
- •1.1.1.2Метод обмена
- •1.1.1.3Сортировка вставками
- •1.1.1.4Метод подсчета
- •1.1.1.5Метод Шелла
- •1.1.1.6Быстрая сортировка
- •1.1.1.6.1Краткое описание алгоритма
- •1.1.1.6.2Алгоритм
- •1.1.1.6.3Оценка эффективности
- •1.1.1.6.4Улучшения
- •1.1.1.6.5Достоинства и недостатки
- •1.1.1.7Пирамидальная сортировка
- •1.1.1.7.1Понятие пирамиды
- •1.1.1.7.2Просеивание вверх
- •1.1.1.7.3Просеивание вниз
- •1.1.1.7.4Построение пирамиды
- •1.1.1.8Сортировка слиянием
- •1.1.1.8.1Процедура слияния
- •1.1.1.8.2Сортировка слиянием
- •1.1.2Методы внешней сортировки
- •1.1.2.1Сбалансированное n-ленточное слияние
- •1.1.3Факторы, учитываемые при выборе метода сортировки.
- •2Размещение данных, основанное на преобразовании кода записи в ее адрес
- •2.1Хеширование данных
- •2.2Методы разрешения коллизий
- •2.3Переполнение таблицы и рехеширование
1.1.1.6.2Алгоритм
Быстрая сортировка использует стратегию «разделяй и властвуй». Шаги алгоритма таковы:
1. Выбираем в массиве некоторый элемент, который будем называть опорным элементом. С точки зрения корректности алгоритма выбор опорного элемента безразличен. С точки зрения повышения эффективности алгоритма выбираться должна медиана, но без дополнительных сведений о сортируемых данных её обычно невозможно получить. Известные стратегии: выбирать постоянно один и тот же элемент, например, средний или последний по положению; выбирать элемент со случайно выбранным индексом.
2. Операция разделения массива: реорганизуем массив таким образом, чтобы все элементы, меньшие или равные опорному элементу, оказались слева от него, а все элементы, большие опорного — справа от него.
Существует два варианта разделения списка:
Вариант 1.
Функция PivotList берет в качестве осевого элемента первый элемент списка и устанавливает указатель pivot в начало списка. Затем она проходит по списку, сравнивая осевой элемент с остальными элементами списка. Обнаружив элемент, меньший осевого, она увеличивает указатель PivotPoint, а затем переставляет элемент с новым номером PivotPoint и вновь найденный элемент. После того, как сравнение части списка с осевым элементом уже произведено, список оказывается разбит на четыре части. Первая часть состоит из первого осевого — элемента списка. Вторая часть начинается с положения f irst+1, кончается в положении PivotPoint и состоит из всех просмотренных элементов, оказавшихся меньше осевого. Третья часть начинается в положении PivotPoint+1 и заканчивается указателем параметра цикла index. Оставшаяся часть списка состоит из еще не просмотренных значений.
Алгоритм.
PivotListdist , first .last)
list обрабатываемый список
first номер первого элемента
last номер последнего элемента
PivotValue=list [first]
PivotPoint=first
for index=f irst+1 to last do
if list [index] <Pivot Value then
PivotPoint=PivotPoint+l
Swap(list [PivotPoint] , list [index] )
end if
end for
// перенос осевого значения на нужное место
Swap (list [first], list [PivotPoint])
return PivotPoint
Рис. 4.1. Пример разбиения элементов списка на четыре группы
Вариант 2.
Второй вариант алгоритма разбиения списка предусматривает наличие двух указателей в списке. Первый идет снизу, второй - сверху. В основном цикле алгоритма нижний указатель увеличивается до тех пор, пока не будет обнаружен элемент, больший PivotValue, а верхний уменьшается пока не будет обнаружен элемент, меньший PivotValue. Затем найденные элементы меняются местами. Этот процесс повторяется пока два указателя не перекроются. Эти внутренние циклы работают очень быстро, поскольку исключаются накладные расходы на проверку конца списка; проблема, однако, состоит в том, что при перекрещивании они
делают лишний обмен. Поэтому алгоритм следует подкорректировать, добавив в него еще один обмен
Вариант 2.
PivotList(list.first,last)
list обрабатываемый список элементов
first номер первого элемента
last номер последнего элемента
PivotValue=list[first]
lower=first
upper=last+l
do
do upper=upper-l until list[upper]<=PivotValue
do lower=lower+l until list[lower]>=PivotValue
Swap(list[upper],list[lower])
until lower>=upper
// устранение лишнего обмена
Swap(list[upper].list [lower])
// перенос оси в нужное место
Swap(list[first],list[upper])
return upper
3. Рекурсивно упорядочиваем подмассивы, лежащие слева и справа от опорного элемента.
4. Базой рекурсии являются наборы, состоящие из одного или двух элементов. Первый возвращается в исходном виде, во втором, при необходимости, сортировка сводится к перестановке двух элементов. Все такие отрезки уже упорядочены в процессе разделения.
Поскольку в каждой итерации (на каждом следующем уровне рекурсии) длина обрабатываемого отрезка массива уменьшается, по меньшей мере, на единицу, терминальная ветвь рекурсии будет достигнута всегда и обработка гарантированно завершится.