Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
4 основи програмування книга.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.77 Mб
Скачать

10.3.1.*Аналіз складності алгоритму

Оцінимо складність алгоритму у термінах C(n), M(n). Оскільки кожна перестановка пов’язана з порівняннями в процедурі ConSwap, M(n)  C(n). Далі, в процедурі Conflict порівняння передує виклику ConSwap, тому загальне число порівнянь не перевищує подвоєного числа викликів ConSwap. Отже, С(n) можна отримати, оцінивши кількість звернень до ConSwap.

Складність I-го етапу C1(n) задовольняє співвідношенню

C1(n)  2C1(n / 2) + C0(n)

де C0(n) - складність процедури Conflict(1, n).

Для С0(n) маємо:

C0(n)  C0(n/2) + 1,

оскільки виклик Conflict(i, n) містить один (рекурсивний) виклик Conflict(2i, n) і ланцюжок викликів обривається при i > n/2. Тому

C0(n)  c0 log2 n.

Таким чином,

C1(n)  2 C1(n / 2) + c0 log2 n.

Нехай k - деяке число. Тоді

C1(n) <= 2 k C1(n/2k) +c0 (2 k-1 log2(n/2 k-1) + ...+ log2(n/2) log2 n)

Оскільки С1(1) = 0, маємо

C1(n) <= c0 (log2 n + 2 log2(n/2) + ... (n/2) log2(2)).

Замінимо log( n/2 i ) на log2 n, посиливши нерівність. Отримаємо

C1(n) <= (c0 log2 n)(1 + 2 + 4 + ... n/2)

Сума в дужках не перевищує n. Тому

C1(n) <= с0 n log2 n (7)

Арифметичний цикл II-го етапу виконується n - 2 разів і кожне повторення містить ConSwap(k, 1) і Conflict(1, k - 1). Тому його складність C2(n) можна оцінити нерівністю C2(n) <= (1+C0(n-1)) + (1+C0(n-2)) + ... + (1+C0(2)) Замінимо C0(i) на C0(n-1), посиливши нерівність. Отримаємо

C2(n) <= n + n C0(n-1) = c1 n log2 n (8)

Остаточно С(n) = C1(n) + C2(n) = (c0+c1) n log2 n, або

С(n) = O( n log2 n ) (9)

Ми показали, що пірамідальне сортування (з точністю до мультиплікативної константи) оптимальне: його складність співпадає ( з тією ж точністю) з нижньою оцінкою задачі.

10.4. Швидке сортування Хоара

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

Ідея К.Хоара полягає у наступному:

Виберемо деякий елемент х масиву А випадковим способом;

Розглядаємо масив у прямому напрямку (і= 1, 2, ...), шукаючи у ньому елемент А[i] не менший, ніж х;

3.Розглядаємо масив у зворотному напрямку(j = n, n-1,..), шукаючи у ньому елемент A[j] не більший, ніж x;

4.Меняємо місцями A[i] і A[j];

Пункти 2-4 повторюємо до тих пір, поки i < j;

В результаті такого зустрічного проходу початок масиву A[1..i] і кінець масиву A[j..n] опиняються розділеними “бар’єром” x: A[k]  x при k < i , A[k]  x при k > j , причому на розділ ми затратимо не більш n/2 перестановок. Тепер залишилось зробити ті ж дії з початком і кінцем масиву, тобто застосувати їх рекурсивно!

Таким чином, процедура Hoare, що описана нами, залежить від параметрів k і m - початкового і кінцевого індексів відрізку масиву, що оброблюється.

Procedure Swap(i, j : Integer);

Var

b : Real;

Begin

b := a[i];

a[i] := a[j];

a[j] := b

End;

Procedure Hoare(L, R : Integer);

Var

left, right : Integer;

x : Integer;

Begin

If L < R

then begin

x := A[(L + R) div 2]; {вибір бар’єру x}

left := L; right := R ;

Repeat {зустрічний прохід}

While A[left] < x do left := Succ(left); {перегляд уперед}

While A[right] > x do right := Pred(right); {перегляд назад}

If left <= right

then begin

Swap(left, right);

left := Succ(left);

right := Pred(right);

end

until left > right;

Hoare(L, right); {сортуємо початок}

Hoare(left, R) {сортуємо кінець}

end

End;

Program QuickSort;

Const

n = 100;

Var

A : array[1..n] of Integer;

{ процедури Swap, Hoare, введення Inp і виведення Out}

Begin

Inp;

Hoare(1, n);

Out

End.

Найбільш важливе місце алгоритму Хоара – правильне опрацювання моменту закінчення руху покажчиків left, right. Помітьте, що в нашій версії переставляються місцями елементи, що дорівнюють x. Якщо в циклах While замінити умови (A[left] < x) і (A[right] > x) на (A[left] <= x) і (A[right] >=x), при x = Max(A) індекси left і right пробіжать весь масив і побіжать далі! Ускладнення ж умов продовження перегляду погіршить ефективність програми.

Аналіз складності алгоритму в середньому, що використовує гіпотезу про рівну ймовірність всіх входів, показує, що

C(n) = O(n log2 n), M(n) = O(n log2 n).

У гіршому випадку, коли в якості бар’єрного вибирається, наприклад, максимальний елемент підмасиву, складність алгоритму квадратична.