Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция по информатике №13.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
121.86 Кб
Скачать

Дополнительно о сортировках

Далее будет рассмотрено несколько видов сортировок, которые работают статистически быстрее всех ранее изученных. Слово «статистически» означает, что быстрота наблюдается в большинстве случаев заполнения массивов случайными значениями. Однако в некоторых, редких, т.н. вырожденных случаях, быстрые сортировки могут утратить свою скорость. Примером вырождения можно считать расположение элементов массива в порядке, обратном требуемому.

Быстрая сортировка Хоара

procedure QuickSort;

procedure InnerSort(L,R: integer);

var

i,j: integer;

x,y,z: single;

begin

i:=L; j:=R;

y:=A[(L+R) div 2];

nMove:=nMove+1;

repeat

x:=A[i]; nMove:=nMove+1;

nCompare:=nCompare+1;

while x<y do

begin

nCompare:=nCompare+1; i:=i+1;

x:=A[i]; nMove:=nMove+1;

end;

z:=A[j];

nMove:=nMove+1;

nCompare:=nCompare+1;

while y<z do

begin

nCompare:=nCompare+1; j:=j-1;

z:=A[j]; nMove:=nMove+1;

end;

if i<=j then

begin

A[i]:=z; A[j]:=x;

nMove:=nMove+2;

inc(i);

dec(j);

end

until i>j;

if L<j then InnerSort(L,j);

if i<R then InnerSort(i,R);

end; // InnerSort

begin

nMove:=0;

nCompare:=0;

InnerSort(1,nCurr);

end;

Сортировки слиянием

Эта группа сортировок не подвержена вырождению. Скорость работы практически такая же, как у сортировки Хоара. Есть некоторый недостаток: для хранения сортируемых массивов требуется вдвое больше памяти, чем у сортировки Хоара.

Элементы, требующие упорядочения (по возрастанию) занимают в массиве A, как и прежде, места с 1-е по nCurr-е. Следующие nCurr мест зарезервированы под временное хранение данных.

Сортировка простым слиянием

Идея сортировки состоит в следующем.

Сортируемый массив из элементов делится пополам (ясно, что это имеет смысл при ). Каждая из его половин сортируется, затем две отсортированные половины «сливаются», образуя отсортированное целое.

Фрагмент процедуры, выполняющей такую сортировку, может выглядеть так:

i:=1; // Место, с которого начинается левая половина

q := (n+1) div 2;

j:=q+1; // Место, с которого начинается правая половина

k:= nCurr; // Место, после которого временно помещается «слитый массив»

СортировкаЛевойПоловины;

СортировкаПравойПоловины;

while (i<=q) and (j<=n) do

// Цикл выполняется, пока обе половины ещё не иссякли

begin

Inc(k);

if A[i]<A[j] then

begin A[k]:=A[i]; Inc(i); end

else

begin A[k]:=A[j]; Inc(j); end;

end;

while i<=q do

// Цикл выполняется, пока левая половина не иссякла

// (правая половина исчерпана)

begin

Inc(k); A[k]:=A[i]; Inc(i);

end;

while j<=r do

// Цикл выполняется, пока правая половина не иссякла

// (левая половина исчерпана)

begin

Inc(k); A[k]:=A[j]; Inc(j);

end;

for i:=1 to n do

// Цикл выполняется для переброски массива из временного места в постоянное

A[i]:=A[i+nCurr];

end;

Ясно, что вызов процедур

СортировкаЛевойПоловины;

СортировкаПравойПоловины;

лучше заменить на рекурсивный вызов самой процедуры, которую мы обсуждаем. Тривиальным случаем следует считать тот, которому соответствует требование отсортировать набор из одного элемента массива.

Ниже приведен полный текст процедуры MergeSort – процедуры сортировки простым слиянием.

procedure MergeSort;

procedure Merge(p, q, r: integer);

var

i, j, k: integer;

begin

i:=p;

j:=q+1;

k:=n;

while (i<=q) and (j<=r) do

begin

Inc(k);

if A[i]<A[j] then

begin

A[k]:=A[i];

Inc(i);

end

else

begin

A[k]:=A[j];

Inc(j);

end;

Inc(nM);

end;

while i<=q do

begin

Inc(k);

A[k]:=A[i];

Inc(i);

end;

while j<=r do

begin

Inc(k);

A[k]:=A[j];

Inc(j);

end;

k:=n;

for i:=p to r do

begin

Inc(k);

A[i]:=A[k];

end;

end;

procedure MergeSortAux(p, r: integer);

var

q: integer;

begin

if p>=r then exit;

q:=(p+r) div 2;

MergeSortAux(p, q);

MergeSortAux(q+1, r);

Merge(p, q, r);

end;

begin

MergeSortAux(1, nCurr);

end;