
- •Основні положення теорії алгоритмів та її застосування
- •Введення до теорії алгоритмів
- •Загальні риси алгоритмів
- •Машина Поста
- •Машина т’юринга
- •Основи лямбда-числення та функціонального програмування
- •Теза Черча-т’юринга про алгоритмічну розв’язність задачі
- •Проблема розв’язності (зависання)
- •Алгоритмічно нерозв’язні задачі
- •Проблема відсутності загального методу вирішення задачі
- •Проблема інформаційної невизначеності задачі
- •Проблема логічної нерозв’язності задачі
- •Побудова машини т’юринга для обчислення деяких простих функцій
- •Введення до оцінки складності алгоритмів
- •Визначення порядку складності алгоритму
- •Оптимізація алгоритмів
- •Структури даних в алгоритмічній мові програмування
- •Визначення алгоритмічної мови програмування
- •Базові елементи сучасної мови програмування: типи даних; екземпляри даних; вирази; оператори; функції; класи.
- •Поняття типу даних
- •Прості типи: числові; символьні; логічні.
- •Тип даних рядок
- •Структуровані типи даних: масиви, записи, множини
- •Типи даних за значенням і за посиланням
- •Сумісність типів та перетворення між типами даних
- •Екземпляри даних: змінні, константи
- •Видимість даних
- •Управління ходом виконання та структурування програм в алгоритмічній мові програмування
- •Вирази, операнди та операції
- •Основні операції: арифметичні; логічні; бульові; з використанням рядків
- •Поняття оператора
- •Прості оператори: присвоювання; виклику функції
- •Оператори управління ходом виконання: розгалуження; вибору; цикли; переходу
- •Структурування програм: функції та класи
- •Параметри функцій: вхідні, результуючі.
- •Рекурсивні функції
- •Файли: текстові, бінарні
- •Алгоритми чисельних методів, апроксимації функцій, інтегрування та вирішення рівнянь з одним невідомим
- •Чисельні методи
- •Особливості вирішення задач чисельними методами, точність та коректність рішень
- •Апроксимації функцій: лінійна інтерполяція; інтерполяційний многочлен Ньютона.
- •Чисельне інтегрування: метод трапецій; метод Сімпсона; метод Сімпсона з оцінкою погрішності.
- •Вирішення рівнянь з одним невідомим: метод простих ітерацій; метод Ньютона; метод парабол.
- •Алгоритми вирішення системи лінійних рівнянь, пошуку екстремуму функції
- •Вирішення системи лінійних рівнянь методом Гауса
- •Пошук екстремуму функцій одної змінної: метод золотого перетину; метод парабол.
- •Пошук екстремуму функцій багатьох змінних: метод координатного спуску; метод найскорішого спуску.
- •Алгоритми обробки масивів
- •Визначення масивів
- •Операції над масивами
- •Упорядкування масивів: сортування вибором; сортування вставкою; бульбашкове сортування; сортування методом Шелла; метод швидкого сортування.
- •Вибір методів сортування
- •Пошук в упорядкованих масивах методом половинного поділу, інтерполяційним методом
- •Застосування індексів для пошуку у невпорядкованих даних
- •Алгоритми обробки даних на основі списків та дерев
- •Визначення списку
- •Види списків: незалежні списки, однозв’язані списки; двозв’язані списки; кільцеві списки; упорядковані списки
- •Основні операції над списками: включення елементу до списку; видалення елементу; перехід між елементами; ітератор для списку
- •Упорядкування та пошук в списках
- •Похідні структури даних: черга, стек, дек
- •Визначення дерева
- •Впорядковані дерева
- •Бінарні дерева
- •Основні операції з бінарними деревами: включення елементу; видалення елементу; обхід дерева
- •Балансування дерева
- •Алгоритми обробки текстових даних на основі регулярних виразів
- •Введення до теорії кінцевих автоматів
- •Графічне представлення кінцевих автоматів
- •Використання кінцевого автомату: синтаксичний аналіз.
- •Реалізація синтаксичного аналізу файлу з розділяючими комами
- •Детерміновані та недетерміновані кінцеві автомати
- •Регулярні вирази
- •Форма Бекуса-Наура для запису регулярних виразів
- •Синтаксичний аналіз регулярних виразів
- •Компіляція регулярних виразів
- •Інструменти для спрощення роботи з регулярними виразами
- •Зіставлення рядків з регулярними виразами.
- •Алгоритми систем числення
- •Введення до систем числення
- •Двійкова система числення
- •Шістнадцяткова система числення
- •Системи числення з нетрадиційними основами
- •Перетворення між різними системами числення
- •Арифметика чисел з плаваючою комою
- •Точність операцій з плаваючою комою
- •Арифметика великих чисел
- •Алгоритми криптографії та хешування
- •Значення випадкових чисел у програмуванні
- •Алгоритми генерації рівномірно розподілених псевдовипадкових чисел
- •Перевірка якості випадкових чисел
- •Кодування з виправленням помилок
- •Стиснення даних
- •Стиснення даних зі словником
- •Алгоритм стиснення даних Лемпела-Зіва
- •Введення до криптографії
- •Елементи теорії порівнянь
- •Шифрування за допомогою випадкових чисел
- •Створення таємного ключа по Діффі-Хеллману
- •Система rsa
- •Алгоритми цифрового підпису
- •Введення до хешування
- •Функції хешування
- •Проста функція хешування рядків
- •Функції хешування з використанням рандомізації
- •Вирішення конфліктів за допомогою лінійного зондування
- •Псевдовипадкове зондування
- •Подвійне хешування
Оптимізація алгоритмів
Алгоритми класу складності NP вважаються неприйнятними для реалізації на сучасних ЕОМ у їх прямому вигляді.
Необхідно знаходити способи оптимізації алгоритмів.
Приклад:
Якщо необхідно перевірити, чи є число 15256677987889881453 складеним, і у нас є число 123567898761 (яке називається свідком), то виявиться, що залишок від ділення одного на інше рівний нулю і перше число є складеним
У даному разі задача класу складності NP може бути зведеною до меншого класу складності за рахунок того, що вирішуватись буде не початкова задача, а допоміжна спрощена задача (наприклад, пошук свідка)
Яким чином можна оптимізувати алгоритм, якщо свідок невідомий?
Розгортання циклів.
Розгортання циклів дозволяє зменшити кількість ітерацій, зменшивши таким чином кількість службових операцій, які необхідно виконати для реалізації циклу (переходи, збільшення значення лічильника, перевірка умови циклу)
Розглянемо простий код:
int[] a = new int[10];
for (int i = 0; i < 10; i++)
{
a[i] = i * 2;
}
Яким чином наведений цикл можна розгорнути?
Варіанти розгортання циклу.
Варіант 1:
for (int i = 0; i < 10; i+=2)
{
a[i] = i * 2;
a[i + 1] = (i + 1) * 2;
}
Варіант 2:
for (int i = 0; i < 10; i += 5)
{
a[i] = i * 2;
a[i + 1] = (i + 1) * 2;
a[i + 2] = (i + 2) * 2;
a[i + 3] = (i + 3) * 2;
a[i + 4] = (i + 4) * 2;
}
Головне правило оптимізації алгоритмів: оптимізовувати необхідно лише той код, час виконання якого можна виміряти.
Команди для вимірювання часу виконання коду в C#:
/* Read the initial time. */
DateTime startTime = DateTime.Now;
Console.WriteLine(startTime);
/* Do something that takes up some time. */
...
/* Read the end time. */
DateTime stopTime = DateTime.Now;
Console.WriteLine(stopTime);
/* Compute the duration between the initial and the end time. */
TimeSpan duration = stopTime - startTime;
Console.WriteLine(duration);
Структури даних в алгоритмічній мові програмування
План лекції
Визначення алгоритмічної мови програмування.
Базові елементи сучасної мови програмування: типи даних; екземпляри даних; вирази; оператори; функції; класи.
Поняття типу даних.
Прості типи: числові; символьні; логічні.
Тип даних рядок.
Структуровані типи даних: масиви, записи, множини.
Типи даних за значенням та за посиланням.
Сумісність типів та перетворення між типами даних.
Екземпляри даних: змінні; константи.
Видимість даних..
Для самостійного вивчення:
Визначення алгоритмічної мови програмування
Алгоритмічна мова програмування – формалізована мова, призначена для розробки програм, які реалізують алгоритми.
Існує еквівалентність між можливостями і характером написання програм алгоритмічною мовою програмування та Машиною Т’юринга і, відповідно, обчислювальними машинами, побудованими на основі архітектури фон Неймана. Таким чином, алгоритм, заданий для машини Т’юринга чи машини з фон-Нейманівською архітектурою, може бути напряму реалізований у вигляді програми на алгоритмічній мові програмування.
Приклад алгоритмічних мов програмування: АЛГОЛ, BASIC, Pascal, C/C++, Java, C#.
Алгоритмічні мови програмування відносяться до імперативної парадигми, згідно з якою описується процес отримання результатів як послідовність інструкцій зміни стану програми. Подібно до того, як з допомогою наказового способу в мовознавстві перелічується послідовність дій, що необхідно виконати, імперативні програми є послідовністю операцій комп'ютеру для виконання. Поширений синонім імперативному програмуванню є процедурне програмування.
Протилежністю імперативної є декларативна парадигма програмування, яка передбачає не процес отримання результату, а формалізований опис результату, який необхідно отримати. До неї відносяться , наприклад, функціональне та логічне програмування.
Функціональне програмування.
Функціональне програмування – парадигма програмування, яка розглядає програму як обчислення математичних функцій та уникає станів та змінних даних. Функціональне програмування наголошує на застосуванні функцій, на відміну від імперативного програмування, яке наголошує на змінах в стані та виконанні послідовностей команд.
Іншими словами, функціональне програмування є способом створення програм, в яких єдиною дією є виклик функції, єдиним способом розбиття програми є створення нового імені функції та задання для цього імені виразу, що обчислює значення функції, а єдиним правилом композиції є оператор суперпозиції функцій. Немає жодних комірок пам'яті, операторів присвоєння, циклів, ні, тим більше, блок схем чи передачі управління
Приклад функціональних мов програмування: Haskell, Erlang, Nemerle, F#.
Логічне програмування.
Логічне програмування — парадигма програмування, а також розділ дискретної математики, що вивчає методи і можливості цієї парадигми, засновані на виведенні нових фактів з даних фактів згідно заданим логічним правилам. Логічне програмування засноване на теорії математичної логіки. Найвідомішою мовою логічного програмування є Prolog, що є за своєю суттю універсальною машиною виводу, що працює в припущенні замкнутості системи фактів.
Першою мовою логічного програмування була мова Planner, в якій була закладена можливість автоматичного виведення результату з даних і заданих правил перебору варіантів (сукупність яких називалася планом). Planner використовувався для того, щоб знизити вимоги до обчислювальних ресурсів (за допомогою методу backtracking) і забезпечити можливість виведення фактів, без активного використання стека. Потім була розроблена мова Prolog, яка не вимагала плану перебору варіантів і була, в цьому смислі, спрощенням мови Planner.
Від мови Planner також відбулися логічні мови програмування QA-4, Popler, Conniver, і QLISP. Мови програмування Mercury, Visual Prolog, Oz і Fril будувалися вже від мови Prolog. На базі мови Planner було розроблене також декілька альтернативних мов логічного програмування, не заснованих на методі backtracking, наприклад, Ether