
- •Основні положення теорії алгоритмів та її застосування
- •Введення до теорії алгоритмів
- •Загальні риси алгоритмів
- •Машина Поста
- •Машина т’юринга
- •Основи лямбда-числення та функціонального програмування
- •Теза Черча-т’юринга про алгоритмічну розв’язність задачі
- •Проблема розв’язності (зависання)
- •Алгоритмічно нерозв’язні задачі
- •Проблема відсутності загального методу вирішення задачі
- •Проблема інформаційної невизначеності задачі
- •Проблема логічної нерозв’язності задачі
- •Побудова машини т’юринга для обчислення деяких простих функцій
- •Введення до оцінки складності алгоритмів
- •Визначення порядку складності алгоритму
- •Оптимізація алгоритмів
- •Структури даних в алгоритмічній мові програмування
- •Визначення алгоритмічної мови програмування
- •Базові елементи сучасної мови програмування: типи даних; екземпляри даних; вирази; оператори; функції; класи.
- •Поняття типу даних
- •Прості типи: числові; символьні; логічні.
- •Тип даних рядок
- •Структуровані типи даних: масиви, записи, множини
- •Типи даних за значенням і за посиланням
- •Сумісність типів та перетворення між типами даних
- •Екземпляри даних: змінні, константи
- •Видимість даних
- •Управління ходом виконання та структурування програм в алгоритмічній мові програмування
- •Вирази, операнди та операції
- •Основні операції: арифметичні; логічні; бульові; з використанням рядків
- •Поняття оператора
- •Прості оператори: присвоювання; виклику функції
- •Оператори управління ходом виконання: розгалуження; вибору; цикли; переходу
- •Структурування програм: функції та класи
- •Параметри функцій: вхідні, результуючі.
- •Рекурсивні функції
- •Файли: текстові, бінарні
- •Алгоритми чисельних методів, апроксимації функцій, інтегрування та вирішення рівнянь з одним невідомим
- •Чисельні методи
- •Особливості вирішення задач чисельними методами, точність та коректність рішень
- •Апроксимації функцій: лінійна інтерполяція; інтерполяційний многочлен Ньютона.
- •Чисельне інтегрування: метод трапецій; метод Сімпсона; метод Сімпсона з оцінкою погрішності.
- •Вирішення рівнянь з одним невідомим: метод простих ітерацій; метод Ньютона; метод парабол.
- •Алгоритми вирішення системи лінійних рівнянь, пошуку екстремуму функції
- •Вирішення системи лінійних рівнянь методом Гауса
- •Пошук екстремуму функцій одної змінної: метод золотого перетину; метод парабол.
- •Пошук екстремуму функцій багатьох змінних: метод координатного спуску; метод найскорішого спуску.
- •Алгоритми обробки масивів
- •Визначення масивів
- •Операції над масивами
- •Упорядкування масивів: сортування вибором; сортування вставкою; бульбашкове сортування; сортування методом Шелла; метод швидкого сортування.
- •Вибір методів сортування
- •Пошук в упорядкованих масивах методом половинного поділу, інтерполяційним методом
- •Застосування індексів для пошуку у невпорядкованих даних
- •Алгоритми обробки даних на основі списків та дерев
- •Визначення списку
- •Види списків: незалежні списки, однозв’язані списки; двозв’язані списки; кільцеві списки; упорядковані списки
- •Основні операції над списками: включення елементу до списку; видалення елементу; перехід між елементами; ітератор для списку
- •Упорядкування та пошук в списках
- •Похідні структури даних: черга, стек, дек
- •Визначення дерева
- •Впорядковані дерева
- •Бінарні дерева
- •Основні операції з бінарними деревами: включення елементу; видалення елементу; обхід дерева
- •Балансування дерева
- •Алгоритми обробки текстових даних на основі регулярних виразів
- •Введення до теорії кінцевих автоматів
- •Графічне представлення кінцевих автоматів
- •Використання кінцевого автомату: синтаксичний аналіз.
- •Реалізація синтаксичного аналізу файлу з розділяючими комами
- •Детерміновані та недетерміновані кінцеві автомати
- •Регулярні вирази
- •Форма Бекуса-Наура для запису регулярних виразів
- •Синтаксичний аналіз регулярних виразів
- •Компіляція регулярних виразів
- •Інструменти для спрощення роботи з регулярними виразами
- •Зіставлення рядків з регулярними виразами.
- •Алгоритми систем числення
- •Введення до систем числення
- •Двійкова система числення
- •Шістнадцяткова система числення
- •Системи числення з нетрадиційними основами
- •Перетворення між різними системами числення
- •Арифметика чисел з плаваючою комою
- •Точність операцій з плаваючою комою
- •Арифметика великих чисел
- •Алгоритми криптографії та хешування
- •Значення випадкових чисел у програмуванні
- •Алгоритми генерації рівномірно розподілених псевдовипадкових чисел
- •Перевірка якості випадкових чисел
- •Кодування з виправленням помилок
- •Стиснення даних
- •Стиснення даних зі словником
- •Алгоритм стиснення даних Лемпела-Зіва
- •Введення до криптографії
- •Елементи теорії порівнянь
- •Шифрування за допомогою випадкових чисел
- •Створення таємного ключа по Діффі-Хеллману
- •Система rsa
- •Алгоритми цифрового підпису
- •Введення до хешування
- •Функції хешування
- •Проста функція хешування рядків
- •Функції хешування з використанням рандомізації
- •Вирішення конфліктів за допомогою лінійного зондування
- •Псевдовипадкове зондування
- •Подвійне хешування
Основні операції над списками: включення елементу до списку; видалення елементу; перехід між елементами; ітератор для списку
Лінійні списки мають підтримувати мінімум чотири обов’язкові операції:
отримання n-го елемента списку для читання чи запису в нього нового значення;
додавання нового елемента в будь-яку позицію в списку;
видалення елемента списку;
визначення довжини (розміру) списку.
Крім того, списки можуть підтримувати наступні операції:
об'єднання в одному списку двох або більше лінійних списків;
розбиття списку на два або більше фрагментів;
створення копії списку;
визначення кількості елементів в списку;
сортування елементів списку;
пошук елемента, що задовольняє певним критеріям.
В залежності від конкретних проблем, які вирішуються шляхом створення лінійного списку, можлива підтримка інших операцій.
Операція включення до списку
Розглянемо приклад створення незалежного списку на основі масиву.
Спочатку задекларуємо клас ListOfNumbers:
using System;
class ListOfNumbers
{
public ListOfNumbers()
{
}
}
Потім передбачимо змінну для збереження списку:
using System;
class ListOfNumbers
{
private double[] Item = new double[20];
public ListOfNumbers()
{
}
}
class Exercise
{
static int Main()
{
ListOfNumbers lstNumbers = new ListOfNumbers();
return 0;
}
}
Передбачимо змінну для збереження довжини списку:
class ListOfNumbers
{
private double[] Item = new double[20];
private int size;
public ListOfNumbers()
{
size = 0;
}
}
class ListOfNumbers
{
const int MaxSize = 100;
private double[] Item = new double[MaxSize];
public int size = 0;
public bool Add(double item)
{
if (size < 20)
{
Item[size] = item;
size++;
return true;
}
return false;
}
}
Передбачимо методи для запису елементу до списку і читання елементу зі списку:
using System;
using System.Collections.Generic;
using System.Text;
namespace ArrayBasedList
{
class ListOfNumbers
{
const int MaxSize = 100;
private int[] items = new int[MaxSize];
public int size = 0;
public void Add(int item)
{
if (size < MaxSize)
{
items[size] = item;
size++;
}
else
{
throw new IndexOutOfRangeException();
}
}
public int GetItem(int pos)
{
if (pos >= 0 & pos <= size)
{
return items[pos];
}
throw new IndexOutOfRangeException();
}
}
class Program
{
static void Main(string[] args)
{
ListOfNumbers numList = new ListOfNumbers();
numList.Add(10);
numList.Add(20);
Console.WriteLine("Кількість елементів: {0}", numList.size);
Console.WriteLine("Другий елемент: {0}", numList.GetItem(1));
Console.ReadLine();
}
}
}
Розглянемо приклад створення однобічно зв’язаного лінійного списку.
Розглянемо наступний код.
using System;
using System.Collections.Generic;
using System.Text;
namespace LinkedList
{
class StudentData
{
public string Name = null;
public string Group = null;
}
class ListOfStudents
{
public int size = 0;
}
class Program
{
static void Main(string[] args)
{
}
}
}
Для можливості зв’язування між елементами необхідно внести модифікації до класу StudentData:
class StudentData
{
public string Name;
public string Group;
public StudentData Next;
}
Готовий приклад:
using System;
using System.Collections.Generic;
using System.Text;
namespace LinkedList
{
class StudentData
{
public string Name = null;
public string Group = null;
public StudentData Next = null;
}
class ListOfStudents
{
public int Size = 0;
public StudentData Head = null;
public int Add(StudentData NewItem)
{
StudentData Dummy = new StudentData();
Dummy = NewItem;
Dummy.Next = Head;
Head = Dummy;
return Size++;
}
public StudentData GetItem(int pos)
{
StudentData current = Head;
for (int i = 0; i < pos & current != null; i++)
{
current = current.Next;
}
return current;
}
}
class Program
{
static void Main(string[] args)
{
ListOfStudents students = new ListOfStudents();
StudentData student;
student = new StudentData();
student.Name = "Петров";
student.Group = "ЕК-123";
students.Add(student);
student = new StudentData();
student.Name = "Сидоров";
student.Group = "ОА-456";
students.Add(student);
student = new StudentData();
student.Name = "Шевченко";
student.Group = "БС-987";
students.Add(student);
Console.WriteLine("Кількість елементів списку: {0}", students.Size);
Console.WriteLine("Ім'я першого студенту за списком: {0}", students.GetItem(0).Name);
Console.WriteLine("Ім'я другого студенту за списком: {0}", students.GetItem(1).Name);
Console.WriteLine("Ім'я третього студенту за списком: {0}", students.GetItem(2).Name);
Console.ReadLine();
}
}
}
Результат представлено на рисунку.
Рисунок 7.1 – Результат роботи програми
Операція видалення зі списку є однією з обов’язкових операцій.
Видалення з лінійного списку на основі масиву:
public void Delete(int pos)
{
if (pos >= 0 && pos <= size)
{
for (int i = pos; i < size; i++)
{
items[i] = items[i + 1];
}
size--;
}
else
{
throw new IndexOutOfRangeException();
}
}
Код методу «Main»:
static void Main(string[] args)
{
ListOfNumbers numList = new ListOfNumbers();
numList.Add(10);
numList.Add(20);
numList.Add(30);
Console.WriteLine("Кількість елементів: {0}", numList.size);
Console.WriteLine("Другий елемент: {0}", numList.GetItem(1));
numList.Delete(1);
Console.WriteLine("Кількість елементів: {0}", numList.size);
Console.WriteLine("Другий елемент: {0}", numList.GetItem(1));
Console.ReadLine();
}
Результат виконання програми наведений на рисунку:
Рисунок 7.2 – Результат виконання програми
Розглянемо видалення елементу зі зв’язаного списку.
Метод видалення першого елементу з голови списку:
public void DeleteFirst()
{
if (Head == null)
{
throw new IndexOutOfRangeException();
}
if (Head.Next != null)
{
Head = Head.Next;
}
else
{
Head = null;
}
Size--;
}
Виконання програми після виконання методу представлено на рисунку.
students.DeleteFirst();
Console.WriteLine("Кількість елементів списку: {0}", students.Size);
Console.WriteLine("Ім'я першого студенту за списком: {0}", students.GetItem(0).Name);
Console.WriteLine("Ім'я другого студенту за списком: {0}", students.GetItem(1).Name);
Рисунок 7.3 – Виконання програми
Метод видалення будь-якого елементу зі списку:
public void Delete(int pos)
{
if (this.GetItem(pos) == null)
{
throw new IndexOutOfRangeException();
}
this.GetItem(pos - 1).Next = this.GetItem(pos + 1);
Size--;
}
Виконання програми після виконання методу представлено на рисунку.
students.Delete(1);
Console.WriteLine("Кількість елементів списку: {0}", students.Size);
Console.WriteLine("Ім'я першого студенту за списком: {0}", students.GetItem(0).Name);
Console.WriteLine("Ім'я другого студенту за списком: {0}", students.GetItem(1).Name);
Рисунок 7.4 – Виконання програми
При роботі зі списками та іншими структурами даних, які передбачають повторення однотипних елементів, поширеним є використання ітераторів – спеціального механізму, який дозволяє обходити елементи структури.
Потреба у ітераторах викликана певними обмеженнями повного обходу усіх елементів структури:
необхідність створення і дублювання власної логіки обходу елементів за умов складної системи визначення необхідних елементів;
складність видалення елементів, обхід яких здійснюється у традиційному параметризованому циклі.