Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ответы на вопросы зачета по информатике.docx с...docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
312.26 Кб
Скачать

11 Пузырьковая сортировка (bubble sort)

Наверное, самый короткий алгоритм сортировки, но и один из самых медленных:

void bSort(int N; int @Buff)

while N>0 do

dec N;

int I=0;

while I<N do

if !(Buff[I]<=Buff[I+1]) then

int Temp =Buff[I+1];

Buff[I+1]=Buff[I];

Buff[I] =Temp;

end

inc I;

end

end

end

Число сравнений всегда N*(N-1)/2, число перестановок в худшем случае такое же (3*N*(N-1)/2 перемещений данных).

Сортировка выборочная (selection sort)

'Очевидный' алгоритм сортировки - перебором находится наименьший элемент, он меняется местами с элементом, стоящим на нулевом месте, затем находится наименьший среди оставшихся и меняется местами с элементом, стоящим на первом месте... Цикл заканчивается когда будут выбраны все элементы:

void sSort(int N; int @Buff)

int I=0;

while I+1<N do

int M=I;

int J=I+1;

while J<N do

if !(Buff[M]<=Buff[J]) then

M=J;

end

inc J;

end

int Temp=Buff[I];

Buff[I] =Buff[M];

Buff[M] =Temp;

inc I;

end

end

Этот алгоритм отличается небольшим числом перестановок (N-1) (операций перемещения данных в три раза больше - 3*(N-1)), но число сравнений очень велико - N*(N-1)/2.

Быстрая сортировка (quick sort)

Алгоритм основан на разделениии сортируемого массива на части и перестановке элементов таким образом, чтобы элементы в левой части массива не превосходили элементов в правой. На каждом шаге выбирается 'средний' элемент массива, в результате ряда перестановок он занимает свое свое законное место, затем каждая из частей упорядочивается:

void qSort(int L, H; int @Buff)

if H<=L+1 then

return

end

int I=L;

int J=H-1;

int K=(L+H)/2;

while TRUE do

while I<K & Buff[I]<=Buff[K] do

inc I;

end

while J>K & Buff[K]<=Buff[J] do

dec J;

end

if I=J then

exit

end

int Temp=Buff[I];

Buff[I]=Buff[J];

Buff[J]=Temp;

select

case I=K:

K=J;

case J=K:

K=I;

end

end

qSort(L, K,@Buff);

qSort(K+1,H,@Buff);

end

Если 'средние' элементы находится не слишком далеко от своих законных мест, все хорошо - оценка времени выполнения ~N*Log(N) (~N+2*N/2+4*N/4+...+N*1), но можно так упорядочить элементы исходного массива, что 'быстрая' сортировка потребует ~N*N операций и, что еще хуже, N фреймов стека. Следующая функция заполняет массив самым неблагоприятным для qSort способом:

void Fill(int N; int @Buff)

if N>0 then

dec N;

Fill(N,@Buff);

int M=(N+1)/2;

Buff[N]=Buff[M];

Buff[M]=N;

end

end

В более сложных реализациях алгоритма 'средний' элемент выбирается как средний из трех или случайным образом. Но как минимум, необходимо заменить один из рекурсивных вызовов циклом, это предотвратит разрушение стека:

void qSort(int L, H; int @Buff)

while TRUE do

if H<=L+1 then

return

end

int I=L;

int J=H-1;

int K=(L+H)/2;

while TRUE do

while I<K & Buff[I]<=Buff[K] do

inc I;

end

while J>K & Buff[K]<=Buff[J] do

dec J;

end

if I=J then

exit

end

int Temp=Buff[I];

Buff[I]=Buff[J];

Buff[J]=Temp;

select

case I=K:

K=J;

case J=K:

K=I;

end

end

if K-L<H-K then

qSort(L, K,@Buff);

L=K+1;

else

qSort(K+1,H,@Buff);

H=K;

end

end

end

В 1959 году американский ученый Дональд Шелл опубликовал алгоритм сортировки, который впоследствии получил его имя – «Сортировка Шелла». Этот алгоритм может рассматриваться и как обобщение пузырьковой сортировки, так и сортировки вставками.

Идея метода заключается в сравнение разделенных на группы элементов последовательности, находящихся друг от друга на некотором расстоянии. Изначально это расстояние равно d или N/2, где N — общее число элементов. На первом шаге каждая группа включает в себя два элемента расположенных друг от друга на расстоянии N/2; они сравниваются между собой, и, в случае необходимости, меняются местами. На последующих шагах также происходят проверка и обмен, но расстояние d сокращается на d/2, и количество групп, соответственно, уменьшается. Постепенно расстояние между элементами уменьшается, и на d=1 проход по массиву происходит в последний раз.

Далее, на примере последовательности целых чисел, показан процесс сортировки массива методом Шелла. Для удобства и наглядности, элементы одной группы выделены одинаковым цветом.

Первое значение, соответствующее расстоянию d равно 10/2=5. На каждом шаге оно уменьшается вдвое. Элементы, входящие в одну группу, сравниваются и если значение какого-либо элемента, стоящего левее того с которым он сравнивается, оказывается больше (сортировка по возрастанию), тогда они меняются местами. Так, элементы путем внутригрупповых перестановок постепенно становятся на свои позиции, и на последнем шаге (d=1) сортировка сводится к проходу по одной группе, включающей в себя все N элементов массива. При этом число требуемых обменов оказывается совсем небольшим.

 

Код программы на C++:

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

#include "stdafx.h" #include <iostream> using namespace std; int i, j, n, d, count; void Shell(int A[], int n) //сортировка Шелла { d=n; d=d/2; while (d>0) { for (i=0; i<n-d; i++) { j=i; while (j>=0 && A[j]>A[j+d]) { count=A[j]; A[j]=A[j+d]; A[j+d]=count; j--; } } d=d/2; } for (i=0; i<n; i++) cout<<A[i]<<" "; //вывод массива } //главная функция void main() { setlocale(LC_ALL,"Rus"); cout<<"Размер массива > "; cin>>n; int *A= new int[n]; //объявление динамического массива for (i=0; i<n; i++) //ввод массива { cout<<i+1<<" элемент > "; cin>>A[i]; } cout<<"\nРезультирующий массив: "; Shell(A, n); delete [] A; //освобождение памяти system("pause>>void"); }

 

Код программы на Pascal:

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

program ShellSorting; uses crt; type massiv=array[1..100] of integer; var i, j, n, d, count: integer; A: massiv; procedure Shell(A: massiv; n: integer); {сортировка Шелла} begin d:=n; d:=d div 2; while (d>0) do begin for i:=1 to n-d do begin j:=i; while ((j>0) and (A[j]>A[j+d])) do begin count:=A[j]; A[j]:=A[j+d]; A[j+d]:=count; j:=j-1; end; end; d:=d div 2; end; writeln; for i:=1 to n do write(' ', A[i]); {вывод массива} end; {основной блок программы} begin write('Размер массива > '); read(n); for i:=1 to n do {ввод массива} begin write(i, ' элемент > '); readln(A[i]); end; write('Результирующий массив: '); Shell(A, n); end.

 

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

 

Сортировка вставками

Сортировка Шелла

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

Худший случай

O(n2)

O(n2)

O(n2)

Лучший случай

O(n)

O(n log n)

O(n log n)

Средний случай

O(n2)

Зависит от расстояния между элементами

O(n log n)

12

21 октября 2013 в 11:50