Амортизований аналіз? (Найгірші гарантії ефективності)


13

Що таке амортизований аналіз? І як це може допомогти мені досягти найгірших гарантій ефективності в моїх програмах?

Я читав, що наступні методи можуть допомогти програмісту домогтися найгірших гарантій ефективності (тобто, моїми власними словами: гарантія, що час роботи програми не перевищить час роботи в гіршому складі):

  • Рандомізовані алгоритми (наприклад, алгоритм кварцового коси є квадратичним у гіршому випадку, але випадкове впорядкування введення дає ймовірні гарантію того, що його час роботи лінійноактичний)
  • Послідовність операцій (наш аналіз повинен враховувати як дані, так і послідовність операцій, які виконує клієнт)
  • Амортизований аналіз (ще один спосіб надання гарантії ефективності - це амортизація витрат шляхом відстеження загальної вартості всіх операцій, поділеної на кількість операцій. У цьому налаштуванні ми можемо дозволити деякі дорогі операції, зберігаючи середню вартість Іншими словами, ми розподіляємо вартість декількох дорогих операцій, присвоюючи частину їх кожній із великої кількості недорогих операцій)

Автор згадував про використання змінної структури даних масиву для Stack як один із прикладів того, як досягти амортизованого аналізу, але я досі не розумію, що таке амортизований аналіз, і як його можна реально реалізувати (структура даних - алгоритм?) Для досягнення гіршого -гарантії виконання

Відповіді:


14

Ви не застосовуєте амортизований аналіз. Це техніка, щоб отримати більш точні Oмежі.

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

У випадку структури даних, підтримуваних масивом, масив потребує зміни розміру раз у раз - коли він заповнений. Це найдорожча операція і вимагає O(n)часу. Усі інші вставки в масив є O(1).

Щоб визначити час виконання для вставки nелементів, ви можете помножити nна найдорожчу операцію O(n), що призводить до загальної поведінки часу виконання O(n^2).

Однак це неточно, оскільки зміна розміру не може траплятися дуже часто.

Якщо говорити про гроші, ви амортизуєте собівартість, коли ви погашаєте свій борг кількома невеликими платежами протягом часу.

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

Після того, як масив буде заповнений на його довжину n, ми можемо подвоїти його розмір. Нам потрібно зробити наступні операції:

  • Виділіть 2nшматки пам’яті
  • копіювати nпредмети

Якщо припустити, що розподілення пам'яті та копіювання відбувається в лінійний час, це буде дуже дорогою операцією. Однак тепер ми можемо використовувати ідею боргу та амортизувати її для нашого аналізу. Тільки ми збираємось амортизувати свій борг ще до того, як насправді це зробимо.
Припустимо, що наш баланс (гроші / час) повертається до 0 (тобто у нас немає боргу, а також у нас немає залишків), коли ми змінили розмір масиву.

Це має таке значення:

  • Вставлення наступних nелементів покриє вартість зміни розміру та копіювання (ми nвикористовували слоти та nневикористані слоти ")

Тепер ми можемо подумати про те, скільки потрібно платити за кожну операцію вставки:

  • Вкладиш
  • Витрати на виділення однієї частини пам’яті
  • витрати на переміщення його в щойно виділену пам'ять

Зараз ми покрили витрати на розподіл пам'яті, копіювання та вставлення наступних nелементів. Однак ми поки нехтували виділенням місця для старих nелементів, а також їх копіюванням.

Ми просто розподіляємо витрати наших старих nелементів на нові (ще не вставлені) nелементи:

  • Витрати на виділення однієї частини пам’яті
  • витрати на переміщення його в щойно виділену пам'ять

Загалом кожна операція з вставкою коштуватиме 5 одиниць. Це платить як за власну вставку, так і за переміщення та виділення місця для себе та одного із старих елементів.

Кожна операція вставки все ще займає постійну кількість часу, але зміна розміру відбувається безкоштовно: ми амортизували її, витрачаючи «більше» часу на кожну вставку.

Як результат, для вставки nелементів потрібен O(n)час.

Тут описані інші методи амортизованого аналізу .


1

Перш за все: це методика аналізу програмного часу, а не техніка реалізації алгоритмів.

Приклад, згаданий у вашому списку, є хорошим: додавання одного елемента до структури даних, що підтримується масивом. Для кожної операції додавання найгіршим випадком є ​​копіювання всіх існуючих елементів. Такий аналіз є занадто песимістичним, тому що вам не доведеться цього робити, якщо ви використовуєте розумну стратегію зміни розміру (помноживши розмір на деякий х> 1,0). Потім аналіз говорить про те, що у вас є зв'язаний O (n ^ 2) - O (n) на кожний пункт n елементів - тоді як фактичний час виконання лише O (n).

Якщо ви середньо оцінюєте величину зміни розміру для всіх вставлених елементів (більшості з яких не потрібно змінювати розмір), ви робите амортизований аналіз. Амортизований аналіз призводить до межі O (n), яка відповідає фактичній поведінці алгоритму.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.