
- •1. Алгоритми та обчислювальна складність
- •1.1. Основи структури даних і алгоритми
- •1.1.2. Поняття абстрактного типу даних. Абстрактні типи даних: стеки, списки, вектори, словники, множини, мультимножини, черги, черги з пріоритетами
- •1.1.3. Кортежі, множини, словники, одно- та двобічнозв'язні списки. Реалізація абстрактних типів даних з оцінюванням складності операцій
- •1.1.4. Базові алгоритми та їх складність: пошук, сортування (прості сортування вибором, вставками, обмінами та удосконалені сортування деревом, сортування Шелла, швидке сортування)
- •1.2. Стратегії розроблення алгоритмів
- •1.2.1. Стратегія «розділяй та володарюй» та приклади застосування.
- •1.2.2. Стратегія балансування та приклади застосування.
- •1.2.3. Динамічне програмування та приклади застосування.
- •1.2.4. Оцінювання складності алгоритму під час застосування кожної стратегії
- •1.3. Моделі обчислень
- •1.3.1. Імперативний та декларативний підходи до програмування
- •1.3.2. Розв'язні, напіврозв'язні та нерозв'язні проблеми. Проблема зупинки
1. Алгоритми та обчислювальна складність
1.1. Основи структури даних і алгоритми
1.1.1. Поняття алгоритму. Визначення його часової та просторової (за обсягом пам’яті) складності
Алгоритм — набір інструкцій, які описують порядок дій виконавця, щоб досягти результату розв'язання задачі за скінченну кількість дій; система правил виконання дискретного процесу, яка досягає поставленої мети за скінченний час. Для візуалізації алгоритмів часто використовують блок-схеми. Для комп'ютерних програм алгоритм є списком деталізованих інструкцій, що реалізують процес обчислення, який, починаючи з початкового стану, відбувається через послідовність логічних станів, яка завершується кінцевим станом. Перехід з попереднього до наступного стану не обов'язково детермінований — деякі алгоритми можуть містити елементи випадковості.
Складність алгоритму – це кількісна оцінка ресурсів, необхідних для його виконання. Вона визначає, наскільки ефективно алгоритм розв’язує задачу, використовуючи ресурси комп’ютера, такі як час і пам’ять.
Розуміння цієї теми є ключовим при розробці ПЗ. Це дає змогу оцінити практичну застосовність алгоритму, оскільки швидкий алгоритм може бути більш привабливим, навіть якщо він менш точний. Крім того, це дає змогу порівнювати різні алгоритми й обирати той, що найбільше відповідає конкретному завданню, а також допомагає прогнозувати його поведінку та передбачати, як зміниться час виконання і споживання пам’яті під час збільшення обсягу даних. Нарешті, складність алгоритму слугує орієнтиром для оптимізації коду, оскільки дає змогу шукати ефективніші рішення.
Як же складність алгоритму впливає на вибір методів розв’язання задач?
Для невеликих завдань часто достатньо використовувати простий і зрозумілий алгоритм, навіть якщо його складність не є оптимальною. Однак, для великих завдань стає критично важливим використовувати алгоритми з низькою складністю. Це дає змогу знизити споживання пам’яті, а також скоротити час виконання, особливо у випадку тих, що потребують розв’язання в реальному часі.
Існують два основні види складності алгоритмів: часова та просторова. Часова – відображає кількість операцій або час, необхідний для виконання алгоритму залежно від розміру вхідних даних. Просторова – оцінює обсяг пам’яті, необхідний для виконання алгоритму. Вони відіграють важливу роль під час вибору ефективних алгоритмів, особливо в умовах обмеженого часу виконання та ресурсів пам’яті.
Складність алгоритму визначає, наскільки ефективно він працює при зростанні обсягу даних, з якими він працює. Зазвичай складність вимірюється часом виконання або кількістю операцій, які потрібні для завершення алгоритму.
Складність алгоритму - це міра його ресурсоємкості, тобто кількості ресурсів (часу, пам'яті), які він витрачає при виконанні, у залежності від розміру вхідних даних. Визначення складності допомагає розуміти, як алгоритм поводиться зі зростанням обсягу даних і оцінювати його ефективність.
Оцінка складності алгоритму - це процес визначення, наскільки ефективно або ресурсоємко працює алгоритм при обробці різних обсягів даних. Цей процес допомагає визначити, наскільки швидко або наскільки багато пам'яті потрібно для виконання алгоритму.
Часова складність: Це кількість операцій, які потрібно для завершення алгоритму. Вимірюється у часових одиницях, таких як секунди, мілісекунди, операції чи тактування процесора.Існують два основних типи складності: часова складність і просторова складність.Ємнісна складність: Це кількість пам'яті, яка потрібна для виконання алгоритму. Вимірюється у байтах або кількості потрібних змінних. Статична складність: Це кількість операторів, які він містить. Оператор може бути будь-якою командою (присвоєння значення змінній, виклик функції, умовний оператор, цикл та інші).
Часова складність часто виражається у величині "O", яка називається "велике O". Наприклад, O(n), де "n" - це розмір вхідних даних. Наприклад, розглянемо простий алгоритм сортування списку чисел методом бульбашки. Він має часову складність O(n^2), оскільки у найгіршому випадку потрібно порівняти кожен елемент з кожним. Просторова складність цього алгоритму - O(1), оскільки він вимагає лише постійного обсягу додаткової пам'яті для збереження проміжних результатів. Цей код просто перевіряє кожну пару сусідніх елементів у списку і обмінює їх, якщо вони не впорядковані. Повторюється цей процес до тих пір, поки весь список не буде відсортований.
Поняття складності алгоритмів. Отже, коли ми говоримо про часову складність алгоритму у формі O(f(n)), де (O: Це означає "в порядку", або "приблизно“, n: Це кількість елементів у вхідних даних, f(n): Це функція, яка визначає, як швидко зростає час виконання алгоритму зі збільшенням n.) , ми фактично описуємо те, як час виконання цього алгоритму змінюється в залежності від розміру вхідних даних, який позначається як n. Якщо ми кажемо, що часова складність алгоритму - O(f(n)), це означає, що час виконання зростає пропорційно зміні функції f(n). Іншими словами, якщо ми збільшимо розмір вхідних даних на певний множник, час виконання алгоритму також збільшиться у відповідному відношенні до значення функції f(n). Наприклад, якщо ми маємо алгоритм з часовою складністю O(n^2), це означає, що час виконання збільшується квадратично з розміром вхідних даних. Іншими словами, якщо ми збільшимо розмір вхідних даних у 2 рази, час виконання збільшиться у 4 рази (2^2).
Часову складність алгоритму O(1), виражає, що час виконання алгоритму не залежить від розміру вхідних даних. У цьому випадку, час виконання залишається постійним, незалежно від обсягу даних.Іншими словами, незалежно від того, чи маємо ми 10 елементів у списку, 1000, або навіть мільйон, час виконання алгоритму буде залишатися сталим. Наприклад, доступ до елементу у масиві за індексом, або отримання значення змінної, не залежить від кількості елементів у масиві чи обсягу даних. Такі операції мають часову складність O(1), оскільки вони виконуються за постійний час, незалежно від розміру вхідних даних.
Отже, ось простий приклад операції з часовою складністю O(1). Давайте розглянемо доступ до елементу у масиві за індексом: У цьому прикладі, незалежно від розміру списку my_list, час доступу до будь-якого елементу за його індексом (наприклад, my_list[0], my_list[2], тощо) залишається сталим. Операція отримання доступу до елементу виконується за постійний час, оскільки індексування списку не залежить від кількості елементів у ньому. Тому часова складність такої операції є O(1).
Лінійна складність O(n) означає, що час виконання алгоритму зростає пропорційно з розміром вхідних даних. Іншими словами, коли розмір вхідних даних (позначений як n) збільшується у 2 рази, час виконання алгоритму також збільшується у 2 рази. Це означає, що кожен елемент у вхідних даних обробляється алгоритмом один раз. Наприклад, якщо у вас є список з n елементів, алгоритм з лінійною складністю буде виконувати n операцій, де кожна операція обробляє один елемент у списку. Отже, коли ми кажемо, що часова складність алгоритму - O(n), ми виражаємо те, що зі збільшенням розміру вхідних даних час виконання зростає лінійно, а саме пропорційно кількості елементів у вхідних даних.
Просторова складність (space complexity) - скільки додаткової пам’яті (оперативної) буде потрібно алгоритму під час виконання, коли збільшується розмір вхідних даних. Варто зазначити, що кількість часу та простору, які потрібні для запуску алгоритму не враховуються в Big O. Це спосіб наближено оцінити, наскільки збільшиться час виконання та об'єм пам'яті при збільшені вхідних даних.