Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичні вказівки до практичних робіт.docx
Скачиваний:
33
Добавлен:
07.06.2015
Размер:
3.36 Mб
Скачать

2.3 Швидке сортування

Рисунок 19 – Схема швидкого сортування

Швидке сортування сортує стовпчики за зростанням.

Швидке сортування - статистично один з найшвидших методів сортування. Воно обганяє всі методи які не використовують внутрішню структуру даних в більшості випадків.

Алгоритм

Швидке сортування використовує метод програмування який називають поділяй і владарюй. Масив ділять на дві частини, так, щоб кожен елемент лівої частини був менший за будь-який з правої. Потім беруть ліву частину і рекурсивно повторюють такі дії для неї. Так само і для правої. Коли розмір частини досягне одного елемента, то масив очевидно буде відсортованим. Запишемо це в мові C.

void qsort(int *a, int l, int r)

{

if(l>=r) return;

int c=partition(int *a, int l, int r);

qsort(a,l,c);

qsort(a,c+1,r);

}

Тут параметри l і r показують межі сортування.

З "владарюй" все має бути очевидно. Залишилось придумати як "поділяти". Порівнювати всі елементи зі всіма неефективно. Краще вибрати якийсь елемент в якості "центрального", і всі елементи які менші за нього перенести в ліву частину, а всі більші - в праву. Можна вибрати будь-який елемент, найкраще за все - випадково.

Рухаючись по масиву зліва направо знаходимо перший елемент, який більший за центральний. Після цього рухаючись зправа наліво знаходимо перший елемент, який менший за центральний. Якщо більший знаходиться лівіше за менший, то ми їх переставляємо, інакше поділ масиву вважаємо завершеним. Виглядає це десь так:

int partition(int *a, int l, int r)

{

int x=a[l];

int i=l-1;

int j=r+1;

while(1)

{

do{ j--; } while(a[j]>x);

do{ i++; } while(a[i]<x);

if(i<j) swap(a+i,a+j);

else return j;

}

}

Швидкість

Очевидно, що функція partition працює за O(n). Спочатку вона раз викликається для всього масиву. Потім два рази для половинок ( O(n/2) + O(n/2) ). Потім чотири рази для четвертинок. А в самому кінці n разів для частин, розмір яких дорівнює 1. Тому бачимо що на кожному рівні рекурсії сумарний час роботи рівний O(n).

Глибина ж рекурсії дорівнює ln(n), якщо масив ділиться на частини рівномірно. Складність алгоритму буде O(n ln(n) ) Якщо ж щоразу одна частина має один елемент, а інша всі решту, то таких поділів буде n. Тоді складність буде O(n2).

2.4 Модифіковані методи сортування

Головний недолік простих методів - обмін ведеться в основному між сусідними елементами. Тому бажано робити якомога ширші обміни.

2.4.1 Метод Шелла

Метод Шелла (Shell D.L., 1959) - метод сортування вставками (включеннями) з відстанями, що зменшуються.

Візьмемо для прикладу масив:

60

16

41

06

59

79

34

15

На першому етапі масив уявно ділиться на підмасиви з елементами, що, скажімо, відстоять один від одного на 4 елементи:

1.

60

 

 

 

59

 

 

 

2.

 

16

 

 

 

79

 

 

3.

 

 

41

 

 

 

34

 

4.

 

 

 

06

 

 

 

15

Кожен з них впорядковується окремо:

1.

59

 

 

 

60

 

 

 

2.

 

16

 

 

 

79

 

 

3.

 

 

34

 

 

 

41

 

4.

 

 

 

06

 

 

 

15

Сортування робиться у кожному підмасиві вставками (методом простого включення).

На другому етапі підмасиви утворюються елементами через один:

1.

59

 

34

 

60

 

41

 

2.

 

16

 

06

 

79

 

15

Одержуємо

1.

34

 

41

 

59

 

60

 

2.

 

06

 

15

 

16

 

79

Після цього весь масив сортується разом. За рахунок попередніх етапів він виявляється вже близьким до відсортованого, тому обмінів необхідно вже не так багато.

Аналіз та експериментальні дослідження методу показують, що цей метод дає кращі результати, якщо розподіл на підмасиви роблять кроками, що не є степенями двійки, а, навпаки, не є множниками один одного.

Рекомендованими є такі послідовності кроків:

У останньому випадку кількість необхідних операцій пропорційна n6/5 = n1,2.