Сортировка (часть 2)
Выбор
В сортировке посредством выбора основная идея состоит в том, чтобы
идти по шагам , находя
-е
наибольшее (наименьшее)
имя и помещая его на его место на
-ом шаге. Простейшая форма
сортировки выбором представлена алгоритмом 15.1:
-е наибольшее
имя
находится очевидным способом просмотром оставшихся
имен. Число
сравнений имен на
-ом шаге равно
, что
приводит к общему числу
сравнений имен
независимо от входа, поэтому ясно, что это не очень хороший способ
сортировки.
Несмотря на неэффективность алгоритма 15.1, идея выбора может привести
и к эффективному алгоритму сортировки. Весь вопрос в том, чтобы найти
более эффективный метод определения -го наибольшего имени, чего
можно добиться, используя механизм турнира с выбыванием. Суть его
такова: сравниваются
, затем сравниваются "победители" (то есть большие
имена) этих
сравнений и т.д.; эта процедура для
показана на рис. 15.1.
Заметим, что для определения наибольшего имени этот процесс требует
сравнений имен; но, определив наибольшее имя, мы обладаем большим
объемом информации о втором по величине (в порядке убывания) имени: оно
должно быть одним из тех, которые "потерпели поражение" от
наибольшего имени. Таким образом, второе по величине имя теперь можно определить,
заменяя наибольшее имя на
и вновь осуществляя сравнение
вдоль пути от наибольшего имени к корню. На рис. 15.2 эта процедура показана для
дерева из рис. 15.1.
Идея турнира с выбыванием прослеживается при сортировке весьма отчетливо,
если имена образуют пирамиду. Пирамида
- это полностью сбалансированное бинарное дерево высоты , в котором все листья находятся на
расстоянии
или
от корня и все потомки узла
меньше его самого; кроме того, в нем все листья уровня
максимально смещены влево. На рис. 15.3 показано множество имен, организованных
в виде пирамиды. Чтобы получить удобное линейное представление дерева, пирамиду
можно хранить по уровням в одномерном массиве: сыновья имени из
-ой позиции есть имена в позициях
и
. Таким образом, пирамида, представленная на рисунке 15.3, принимает
вид
![\begin{center}
\begin{tabular}{ccccccccccccc}
i: & 1 & 2 & 3 & 4 & 5 & 6
& 7 & 8 & 9 & 10 & 11 & 12\\
x_i & 94 & 93 & 75 & 91 & 85 & 44 &
51 & 18 & 48 & 58 & 10 & 34
\end{tabular}
\end{center}](/sites/default/files/tex_cache/c58972d63f5971b27bbbe135f3be8f38.png)
Заметим, что в пирамиде наибольшее имя должно находиться в корне и, таким
образом, всегда в первой позиции массива, представляющего пирамиду. Обмен
местами первого имени с -м помещает наибольшее имя в его
правильную позицию, но нарушает свойство
пирамидальности в первых
именах. Если мы можем сначала
построить пирамиду, а затем эффективно
восстановить ее, то все в порядке, так как тогда можно производить сортировку
следующим образом:
построить пирамиду из
,
Это общее описание пирамидальной сортировки.
![Использование турнира с выбыванием для отыскания наибольшего имени.Путь наибольшего имени показан жирной линией](/EDI/31_12_18_1/1546208382-685/tutorial/147/objects/15/files/15_01.jpg)
Рис. 15.1. Использование турнира с выбыванием для отыскания наибольшего имени.Путь наибольшего имени показан жирной линией
Процедура RESTORE восстановления пирамиды из
последовательности
в предположении, что
все поддеревья суть пирамиды, такова:
Переписывая это итеративным способом и дополняя деталями, мы получим алгоритм 15.2.
Распределяющая сортировка
Обсуждаемый здесь алгоритм сортировки отличается от рассматривавшихся до
сих пор тем, что он основан не на сравнениях между именами, а на представлении
имен. Мы полагаем, что каждое из имен имеет
вид
![x_i = (x_{i,p},x_{i,p - 1},\ldots,x_{i,1} )](/sites/default/files/tex_cache/8586482b656c5ce813ca9175f92f5ab5.png)
![x_i = (x_{i,p},x_{i,p - 1},\ldots,x_{i,1} ) < (x_{j,p}^,,x_{j,p -
1},\ldots,x_{j,1} ) = x_j](/sites/default/files/tex_cache/5c12aba8dc327d7eeca37b97d7d3a595.png)
![t \leqslant p](/sites/default/files/tex_cache/f6b2e8c7c80a857d9825d63468de070a.png)
![x_{i,l} = x_{j,l}](/sites/default/files/tex_cache/a8f980b3de798943da8e9e4b35ef5de1.png)
![l > t](/sites/default/files/tex_cache/a3f8bce3fee2b94eaa6831e0b5f3417e.png)
![x_{i,t} < x_{j,t}](/sites/default/files/tex_cache/8432bdb65e75540af06c94c25fdabe68.png)
![0
\leqslant x_{i,l} < r](/sites/default/files/tex_cache/ebdb016ec626a26f0b766e270d300570.png)
![r](/sites/default/files/tex_cache/4b43b0aee35624cd95b910189b3dc231.png)
![p](/sites/default/files/tex_cache/83878c91171338902e0fe0fb97a8c47a.png)
![r](/sites/default/files/tex_cache/4b43b0aee35624cd95b910189b3dc231.png)
Цифровая распределяющая сортировка
Цифровая распределяющая сортировка основана на наблюдении, что если имена
уже отсортированы по младшим разрядами , то их
можно полностью отсортировать, сортируя только по старшим разрядам
при условии, что сортировка осуществляется таким
образом, чтобы не нарушить
относительный порядок имен с одинаковыми цифрами в старших разрядах. Заметим,
что к самой таблице обращаются по правилу "первым включается – первым
исключается", и поэтому лучшим способом представления являются очереди. В
частности, предположим, что с каждым ключом
ассоциируется
поле связи
; тогда эти поля связи можно использовать для
сцепления всех имен в таблице вместе
во входную очередь
. При помощи полей связи можно также сцеплять
имена в очереди
, используемые для
представления стопок. После того как имена распределены по
стопкам, очереди, представляющие эти стопки, связываются вместе для получения
вновь таблицы
. Алгоритм 15.4. представляет эту процедуру в
общих чертах (очереди описаны в
"Алгоритмы на абстрактных структурах данных"
).
В результате применения алгоритма очередь
будет
содержать имена в порядке возрастания; то есть имена будут связаны в порядке
возрастания полями связи, начиная с головы очереди
.