Сортировка бинарными включениями
Если воспользоваться отсортированностью «готовой» последовательности, то процесс вставки нового элемента может быть ускорен. Это достигается за счет применения бинарного (дихотомического) поиска места вставки очередного элемента. Программа приведена в листинге 8.4.
Листинг 7.4. Сортировка бинарными включениями
Procedure SortBinInsert (var a: TData);
Var
i,j,left,right,m: integer;
tmp : integer;
Begin
for i:=2 to N do begin
tmp:=a[i]; left:=1; right:=i-1;
while left<=right do begin
m:=(left+right)div 2;//определение индекса среднего элемента
if tmp<a[m] then
right:=m-1 // сдвиг правой
Else
left:=m+1 //или левой границы
end;
for j:=i-1 downto left do a[j+1]:=a[j]; // сдвиг элементов
a[left]:=tmp; // вставка элемента на нужное место
end;
End; // BinInsert
Число сравнений C~N*logN, так как поиск места вставки ищется каждый раз только в половине интервала. Но это улучшение касается только числа сравнений. Поскольку пересылка элементов – более трудоемкая операция, то это улучшение не является решающим: число перестановок по-прежнему ~N2.
Для больших N сортировка вставками оказывается не очень подходящим методом: сдвиг ряда элементов для вставки одного – неэкономно. Казалось бы, гораздо эффективнее переставлять только некоторые элементы и на большие расстояния. Действительно, такой метод сортировки есть: это сортировка Шелла. Мы рассмотрим ее несколько позже.
Сортировка обменом
Сортировка простым обменом
|
|
Сортировка методом пузырька – это трогательное название запоминают все. Но далеко не все знают, что этот метод в полной мере воплощает принцип обменной сортировки: сравниваются и обмениваются местами два соседних элемента. При чем здесь пузырек? Если представить массив высоким и узким сосудом с жидкостью, а элементы массива – пузырьками, вес которых пропорционален величине ключа элемента, то каждый проход по массиву заставляет пузырек подняться кверху и занять место, соответствующее его весу. Алгоритм приведен в листинге 7.5.
Листинг 7.5. Сортировка методом пузырька
Procedure SortBubble (var a: TData);
Var
i,j: integer;
tmp : integer;
Begin
for i:=2 to N do begin
for j:=N downto i do
if a[j-1]>a[j] then begin // сравнение элементов
tmp:=a[j]; a[j]:=a[j-1]; a[j-1]:=tmp // обмен местами
End
End;
End;
Шейкер-сортировка
Оптимизация предыдущего алгоритма включает в себя следующее:
- массив можно считать уже упорядоченным, если на последнем проходе не было ни одной перестановки элементов
- сравнение пар элементов можно производить только до места последней перестановки: раз не было перестановок, значит – дальше элементы упорядочены
- при прохождении массива слева направо (снизу вверх) поднимается легкий пузырек. Почему бы не двигаться по массиву в обратном направлении – сверху вниз, опуская тяжелый пузырек?
Эти моменты учтены в шейкер-сортировке (от англ. shake – трясти), приведенной в листинге 7.6.
|
|
Листинг 7.6. Шейкер-сортировка
Procedure SortShaker (var a: TData);
Var
j,left,right: integer;
tmp : integer;
Last :integer; // место последней перестановки
Begin
left:=2; right:=N; last:=N;
Repeat
for j:=right downto left do //поднимаются легкие пузырьки
if a[j-1]>a[j] then begin
tmp:=a[j]; a[j]:=a[j-1]; a[j-1]:=tmp;
last:=j
end;
left:=last+1; // запомнили место последней перестановки
for j:=left to right do //опускаются тяжелые пузырьки
if a[j-1]>a[j] then begin
tmp:=a[j]; a[j]:=a[j-1]; a[j-1]:=tmp;
last:=j
end;
right:=last-1; // запомнили место последней перестановки
until left>right;
End; //Shaker
Число сравнений в алгоритме простого обмена равно C=1/2(N2-N), а минимальное и максимальное количества пересылок равны: Mmin=0, Mmax~(N2-N). Наименьшее число сравнений в шейкер-сортировке Cmin=(N-1) – это соответствует единственному проходу по упорядоченному массиву.
Все усовершенствования сортировки обменом приводят только к уменьшению числа сравнений. Но поскольку именно перестановка элементов занимает, как правило, гораздо большее время, то эти усовершенствования не приводят к значительному эффекту. Анализ показывает, что сортировка методом пузырька (и даже ее улучшенный вариант – шейкер-сортировка) менее эффективна, чем сортировка вставками и обменом.
|
|
Сортировка Шелла
Рассмотрим одно из усовершенствований простой сортировки обменом – метод убывающих приращений. Оно заключается в том, что на каждом этапе сравниваются и обмениваются местами элементы, стоящие друг от друга на некотором расстоянии. Это расстояние (шаг) на первом этапе равно примерно половине длине массива, с каждым этапом уменьшается, и на последнем этапе шаг равен единице. Улучшение происходит оттого, что на начальных этапах в сортировке участвуют немного элементов, с каждым этапом повышается отсортированность массива, и на последнем этапе, который есть сортировка простыми вставками, массив уже почти отсортирован, и перемещений элементов немного.
В этой сортировке важен правильный выбор величины шагов. Анализ показывает, что величины шагов не должны быть кратны друг другу, чтобы достигнуть лучших результатов. Кнут рекомендует такие последовательности (записанные в обратном порядке):
1, 4, 13, 40, 121, … , где stepk-1=3*stepk+1,
1, 3, 7. 15, 31, …где stepk-1=2*stepk+1.
|
|
В листинге 7.7 шаги выбирались по формуле stepk= stepk-1*3/5, начиная с step1=N div 2 и заканчивая шагом, равным единице.
Листинг 7.7. Сортировка Шелла
Дата добавления: 2021-01-21; просмотров: 90; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!