Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
более вразумительные ответы.doc
Скачиваний:
5
Добавлен:
19.04.2019
Размер:
379.39 Кб
Скачать

41. Алгоритм Сортировка вставками.

Это изящный и простой для понимания метод. Вот в чем его суть: создается

новый массив, в который мы последовательно вставляем элементы из

исходного массива так, чтобы новый массив был упорядоченным. Вставка

происходит следующим образом: в конце нового массива выделяется

свободная ячейка, далее анализируется элемент, стоящий перед пустой

ячейкой (если, конечно, пустая ячейка не стоит на первом месте), и если этот

элемент больше вставляемого, то подвигаем элемент в свободную ячейку

(при этом на том месте, где он стоял, образуется пустая ячейка) и сравниваем

следующий элемент. Так мы прейдем к ситуации, когда элемент перед пустой

ячейкой меньше вставляемого, или пустая ячейка стоит в начале массива.

Помещаем вставляемый элемент в пустую ячейку. Таким образом, по

очереди вставляем все элементы исходного массива. Очевидно, что если до

вставки элемента массив был упорядочен, то после вставки перед

вставленным элементом расположены все элементы, меньшие его, а после -

большие. Так как порядок элементов в новом массиве не меняется, то

сформированный массив будет упорядоченным после каждой вставки. А

значит, после последней вставки мы получим упорядоченный исходный

массив. Вот как такой алгоритм можно реализовать на языке

программирования Pascal:

Program InsertionSort;

Var A,B : array[1..1000] of integer;

N,i,j : integer;

Begin

{Определение размера массива A (N) и его заполнение}

{сортировка данных}

for i:=1 to N do

begin

j:=i;

while (j>1) and (B[j-1]>A[i]) do

begin

B[j]:=B[j-1];

j:=j-1;

end;

B[j]:=A[i];

end;

{Вывод массива B}

End.

49

42. Алгоритм Сортировка Шейкером.

Когда данные сортируются не в оперативной памяти, а на жестком диске,

особенно если ключ связан с большим объемом дополнительной

информации, то количество перемещений элементов существенно влияет на

время работы. Этот алгоритм уменьшает количество таких перемещений,

действуя следующим образом: за один проход из всех элементов выбирается

минимальный и максимальный. Потом минимальный элемент помещается в

начало массива, а максимальный, соответственно, в конец. Далее алгоритм

выполняется для остальных данных. Таким образом, за каждый проход два

элемента помещаются на свои места, а значит, понадобится N/2 проходов,

где N - количество элементов. Реализация данного алгоритма выглядит так:

Program ShakerSort;

Var A : array[1..1000] of integer;

N,i,j,p : integer;

Min, Max : integer;

Begin

{Определение размера массива A - N) и его заполнение}

{сортировка данных}

for i:=1 to n div 2 do

begin

if A[i]>A[i+1] then

begin

Min:=i+1;

Max:=i;

end

else

begin

Min:=i;

Max:=i+1;

end;

for j:=i+2 to n-i+1 do

if A[j]>A[Max] then

Max:=j

else

if A[j]<A[Min] then

Min:=j;

{Обмен элементов}

P:=A[i];

A[i]:=A[min];

A[min]:=P;

if max=i then

max:=min;

P:=A[N-i+1];

A[N-i+1]:=A[max];

A[max]:=P;

50

end; {Вывод отсортированного массива A} … End.

51

43. Алгоритм Быстрая сортировка.

Как и в сортировке слиянием, массив разбивается на две части, с условием,

что все элементы первой части меньше любого элемента второй. Потом

каждая часть сортируется отдельно. Разбиение на части достигается

упорядочиванием относительно некоторого элемента массива, т. е. в первой

части все числа меньше либо равны этому элементу, а во второй,

соответственно, больше либо равны. Два индекса проходят по массиву с

разных сторон и ищут элементы, которые попали не в свою группу. Найдя

такие элементы, их меняют местами. Тот элемент, на котором индексы

пересекутся, и определяет разбиение на группы. Классическая реализация

алгоритма выглядит так:

Что же делает данный алгоритм таким быстрым? Ну во-первых, если массив

каждый раз будет делится на приблизительно равные части, то для него

будет верно то же соотношение, что и для сортировки слиянием, т. е. время

работы будет O(nlog2n). Это уже само по себе хорошо. Кроме того, константа

при nlog2n очень мала, ввиду простоты внутреннего цикла программы. В

комплексе это обеспечивает огромную скорость работы. Но как всегда есть

одно «но». Вы, наверное, уже задумались: а что если массив не будет

делится на равные части? Классическим примером является попытка

«быстро» отсортировать уже отсортированный массив. При этом данные

каждый раз будут делиться в пропорции 1 к n-1, и так n раз. Общее время

работы при этом будет O(n2), тогда как вставкам, для того чтобы «понять»,

что массив уже отсортирован, требуется всего-навсего O(n). А на кой нам

сортировка, которая одно сортирует хорошо, а другое плохо? А собственно,

что она сортирует хорошо? Оказывается, что лучше всего она сортирует

случайные массивы (порядок элементов в массиве случаен). И поэтому нам

предлагают ввести в алгоритм долю случайности. А точнее, вставить

randomize и вместо r:=A[p]; написать r:=A[random(q-p)+p]; т. е. теперь мы

разбиваем данные не относительно конкретного, а относительно случайного

элемента. Благодаря этому алгоритм получает приставку к имени

«вероятностный». Особо недоверчивым предлагаю на своем опыте убедится,

что данная модификация быстрой сортировки сортирует любые массивы

столь же быстро.

А теперь еще один интересный факт: время O(nlog2n) является минимальным

для сортировок, которые используют только попарное сравнение элементов и

не использует структуру самих элементов. Тем, кому интересно, откуда это

взялось, рекомендую поискать в литературе, доказательство я здесь

приводить не намерен, не Дональд Кнут, в конце концов :-). Но вы обратили

внимание, что для рассмотренных алгоритмов в принципе не важно, что

сортировать - такими методами можно сортировать хоть числа, хоть строки,

хоть какие-то абстрактные объекты. Следующие сортировки могут

сортировать только определенные типы данных, но за счет этого они имеют

рекордную временную оценку O(n).

Program QuickSort;

Var A : array[1..1000] of integer;

N,T : integer;

52

Procedure Sort(p,q : integer); {p,q - индексы начала и конца сортируемой части

массива}

Var i,j,r : integer;

Begin

if p<q then {массив из одного элемента тривиально упорядочен}

begin

r:=A[p];

i:=p-1;

j:=q+1;

while i<j do

begin

repeat

i:=i+1;

until A[i]>=r;

repeat

j:=j-1;

until A[j]<=r;

if i<j then

begin

T:=A[i];

A[i]:=A[j];

A[j]:=T;

end;

end;

Sort(p,j);

Sort(j+1,q);

end;

End;

Begin

{Определение размера массива A - N) и его заполнение}

{запуск сортирующей процедуры}

Sort(1,N);

{Вывод отсортированного массива A}

End.

53

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]