
- •Програмування
- •1. Алгоритми 12
- •2. Комп’ютери і програми 47
- •3. Мова програмування паскаль 56
- •4. Прості типи даних. Лінійні програми 61
- •5. Процедурне програмування 73
- •6. Програмування розгалужень 79
- •7. Оператори повторення з параметром. Масиви 99
- •7.13. Задачі і вправи 114
- •8. Ітераційні цикли 116
- •8.6. Задачі і вправи 124
- •9. Рекурсія 126
- •9.4. Задачі і вправи 135
- •10. Швидкі алгоритми сортування і пошуку 137
- •10.8. Задачі і вправи 148
- •11. Складні типи даних: записи і файли 150
- •11.11. Задачі і вправи 169
- •12. Множини 172
- •12.5. Задачі і вправи 175
- •13. Динамічні структури даних 176
- •14. Методологія структурного програмування: підсумки 192
- •1. Алгоритми
- •1.1. Змістовне поняття алгоритму
- •1.2. Виконавець алгоритмів і його система команд
- •1.3. Основні властивості алгоритмів
- •1.4. Величини
- •1.5. Типи величин
- •1.6. Цілі числа
- •1.7. Дійсні числа
- •1.8. Рядкові величини
- •У слові w знайти слово p і замінити його словом q.
- •1.9. Форми запису алгоритмів
- •1:Кінець.
- •X2 присвоїти значення x1
- •1:Кінець.
- •1.10. Команди управління
- •1.11. Блок - схеми
- •1.12. Допоміжні алгоритми
- •1.13. Базові структури управління
- •1.14. Абстракція даних
- •Приклад 1.7. Атд Планіметрія (виконавець Геометр)
- •1.15. Структурне програмування
- •1.16. Парадигма процедурного програмування
- •2. Комп’ютери і програми
- •2.1. Комп’ютер як універсальний Виконавець
- •2.1.1. Зовнішні пристрої комп’ютера
- •2.1.2. Центральні пристрої комп’ютера
- •2.1.3. Поняття про машинну мову
- •2.2. Мови програмування високого рівня
- •2.2.1. Коротка історія розвитку мов програмування
- •2.2.2. Про історію розвитку методів проектування програм
- •2.3. Основні етапи проектування програми
- •2.4. Технологія трансляції програм
- •2.5. Поняття про систему програмування
- •3. Мова програмування паскаль
- •3.1. Алфавіт мови
- •3.2. Концепція даних
- •3.3. Імена та їх застосування
- •3.4. Структура Pascal-програми
- •3.5. Поняття про лексику, прагматику, синтаксис і семантику мови програмування
- •3.6. Синтаксичні діаграми як засіб визначення мови програмування
- •4. Прості типи даних. Лінійні програми
- •4.1. Заголовок програми
- •4.2. Константи і їх використання. Розділ констант
- •4.3. Змінні програми. Розділ змінних
- •4.4. Стандартні прості типи даних
- •4.5. Тип даних Integer
- •4.6. Тип даних Real
- •4.7. Тип даних Сhar
- •4.8. Поняття виразу. Значення виразу. Тип виразу
- •4.9. Розділ операторів. Оператор присвоювання
- •4.10. Оператори введення - виведення
- •4.11. Приклад лінійної програми
- •4.12. Поняття складності виразу. Оптимізація обчислень
- •4.13. Оптимізація лінійних програм
- •4.14. Задачі і вправи
- •5. Процедурне програмування
- •5.1. Опис процедури
- •5.2. Формальні параметри. Локальні і глобальні об’єкти
- •5.3. Оператор процедури. Фактичні параметри
- •5.4. Функції
- •5.5. Приклади
- •6. Програмування розгалужень
- •6.1. Поняття умови. Тип даних Boolean (логічний)
- •6.2. Складений оператор
- •6.3. Оператори вибору: умовний оператор
- •6.4. Приклади
- •6.5. Задачі вибору й упорядкування
- •6.5.1. Задачі вибору
- •6.5.2. Дерево розв’язувань задачі вибору
- •6.5.3. Задачі на зважування
- •6.5.4. Ефективність алгоритму як кількість його кроків
- •6.5.5. Вибір даного елемента
- •6.6. Задачі упорядкування
- •6.6.1. Упорядкування елементів
- •6.6.2. Порівняння, перестановки і пересилання
- •6.7. Оптимізація розгалужень
- •6.8. Розділ типів. Перелічуваний тип
- •6.9. Оператори вибору: оператор варіанта
- •6.10. Вправи
- •7. Оператори повторення з параметром. Масиви
- •7.1. Оператор циклу з параметром
- •7.2. Циклічні програми. Складність циклічної програми. Оптимізація циклічних програм
- •7.3. Обмежені типи
- •7.4. Складні (складені) типи
- •7.5. Регулярний тип. Масиви
- •7.6. Пошук елемента в масиві
- •7.7. Ефективність алгоритму за часом
- •7.8. Мітки. Оператор переходу. Застосування оператора переходу для дострокового виходу з циклу
- •7.9. Постановка задачі сортування
- •7.10. Сортування масивів
- •7.10.1. Прості алгоритми сортування
- •7.11 Сортування обмінами
- •7.12. Сортування вибором
- •7.13. Задачі і вправи
- •8. Ітераційні цикли
- •8.1. Оператори повторення While і Repeat
- •8.2. Алгоритми пошуку і сортування. Лінійний пошук у масиві
- •8.3. Поліпшений алгоритм сортування обмінами
- •8.4. Бінарний пошук в упорядкованому масиві
- •8.5. Алгоритми сортування масивів (продовження). Сортування вставками
- •8.5.1 * Ефективність алгоритму
- •8.6. Задачі і вправи
- •9. Рекурсія
- •9.1. Рекурсивно-визначені процедури і функції
- •9.2. Приклади рекурсивних описів процедур і функцій
- •I стержень j стержень 6-I-j стержень
- •I стержень j стержень 6-I-j стержень
- •I стержень j стержень 6-I-j стержень
- •9.3. Переваги і недоліки рекурсивних алгоритмів
- •9.4. Задачі і вправи
- •10. Швидкі алгоритми сортування і пошуку
- •10.1. Нижня оцінка часу задачі сортування масиву за числом порівнянь
- •10.2. Швидкі алгоритми сортування: Сортування деревом
- •10.2.1. *Аналіз складності алгоритму
- •10.3. Пірамідальне сортування
- •10.3.1.*Аналіз складності алгоритму
- •10.4. Швидке сортування Хоара
- •10.5. Пошук k-того в масиві. Пошук медіани масиву
- •10.6.* Метод “розділяй і володій”
- •10.7.* Метод цифрового сортування
- •10.8. Задачі і вправи
- •11. Складні типи даних: записи і файли
- •11.1. Складні типи даних у мові Pascal
- •11.2. Записи
- •11.3. Записи з варіантами
- •11.4. Оператор приєднання
- •11.5. Рядки і засоби їх обробки
- •Процедури і функції типу String.
- •11.7. Файли. Управління файлами
- •11.8. Основні задачі обробки файлів
- •11.9. Сортування файлів
- •11.9.1. Алгоритм сортування злиттям
- •11.9.2. Аналіз складності алгоритму
- •11.10. Задача корегування файла
- •11.11. Задачі і вправи
- •12. Множини
- •12.1. Множинний тип
- •12.2. Конструктор множини
- •12.3. Операції і відношення над множинами
- •12.4. Застосування множин у програмуванні
- •12.5. Задачі і вправи
- •13. Динамічні структури даних
- •13.1. Стандартні динамічні структури
- •13.2. Посилальний тип даних. Посилання
- •13.3. Програмування динамічних структур даних
- •13.4. Стеки, списки, черги
- •13.5. Задачі
- •13.6. Дерева
- •13.7. Бінарні дерева
- •13.8. Задачі
- •14. Методологія структурного програмування: підсумки
- •14.1. Основні структури управління
- •14.2. Основні структури даних
- •14.3. Методологія програмування “зверху-вниз”
- •14.4. Приклад: Система лінійних рівнянь
- •14.5. Проектування модулів. Модуль rat
- •14.6. Реалізація модуля
- •14.7. Висновки (модульне програмування)
- •14.8. Заключне зауваження: переходимо до об’єктів
10.2.1. *Аналіз складності алгоритму
Оцінимо складність алгоритму в термінах M(n), C(n). Перш за все відмітимо, що алгоритм TreeSort працює однаково на всіх входах, так що його складність у гіршому випадку співпадає зі складністю в середньому.
Припустимо, що n - степінь 2 (n = 2l). Тоді дерево сортування має l + 1 рівень (глибину l). Побудова рівня I потребує n / 2I рівнянь і пересилань. Таким чином, I-ий етап має складність
C1(n) = n/2 + n/4 + ... + 2 + 1 = n - 1, M1(n) = C1(n) = n - 1
Для того, щоб оцінити складність II-го етапу С2(n) і M2(n) відмітимо, що кожний шлях просівання має довжину l, тому кількість порівнянь пересилань при просіванні одного елемента пропорційна l. Таким чином, M2(n) = O(l n), C2(n) = O(l n).
Оскільки
l = log2n, M2(n)=O(n log2 n)), C2(n)=O(n log2 n),
але С(n) = C1(n) + C2(n), M(n) = M1(n) + M2(n).
Так як C1(n) < C2(n), M1(n) < M2(n),
остаточно отримаємо оцінки складності алгоритму TreeSort за часом:
M(n) = O(n log2 n), C(n) = O(n log2 n),
У загальному випадку, коли n не є степенем 2, дерево сортування будується дещо по іншому. “Зайвий” елемент (елемент, для якого немає пари) переноситься на наступний рівень. Легко бачити, що при цьому глибина дерева дорівнює [log2 n] + 1. Удосконалення алгоритму II етапу очевидне. Оцінки при цьому міняють лише коефіцієнти-множники. Алгоритм TreeSort має суттєвий недолік: для нього потрібна додаткова пам’ять розміром 2n - 1.
10.3. Пірамідальне сортування
Алгоритм пірамідального сортування HeapSort також використовує представлення масиву у виді дерева. Цей алгоритм не потребує додаткових масивів; він сортує “на місці”. Розглянемо спочатку метод представлення масиву у виді дерева:
Нехай А [1 .. n] – деякий масив. Зіставимо йому дерево, використовуючи наступні правила:
1. A[1] - корінь дерева ;
2. Якщо A[i] - вузол дерева і 2i n,
то A[2*i] - вузол - “лівий син” вузла A[i]
3. Якщо A[i] - вузол дерева і 2i + 1 n,
то A[2*i+1] - вузол - “правий син” вузла A[i]
лівий син правий син
батько
Рис 10.4. Правило представлення дерева в масиві.
Правила 1 - 3 визначають у масиві структуру дерева, причому глибина дерева не перевищує [log2 n] + 1. Вони ж задають спосіб руху по дереву від кореня до листя. Рух уверх задається правилом 4:
4.Якщо A[i] - вузол дерева і i > 1
то A[i mod 2] - вузол - “батько” вузла A[i];
Приклад 10.1. Нехай A = [45 13 24 31 11 28 49 40 19 27] – масив. Відповідне йому дерево має вид:
Рис. 10.5 Представлення масиву в дереві.
Зверніть увагу на те, що всі рівні дерева, за винятком останнього, повністю заповнені, останній рівень заповнений зліва і індексація елементів масиву здійснюється зверху-вниз і зліва-направо. Дерево впорядкованого масиву задовольняє наступним властивостям:
A[i] A[2*i], A[i] A[2*i+1], A[2*i] A[2*i+1].
Як це не дивно, алгоритм HeapSort спочатку будує дерево, яке задовольняє прямо протилежним співвідношенням
A[i] A[2*i], A[i] A[2*i+1] (6)
а потім міняє місцями A[1] (найбільший елемент) і A[n].
Як і TreeSort, алгоритм HeapSort працює в два етапи:
І.Побудова дерева, що сортує;
І І.Просівання елементів по дереву, що сортує.
Дерево, що представляє масив, називається сортуючим, якщо виконуються умови (6). Якщо для деякого і ця умова не виконується, будемо говорити, що має місце (сімейний) конфлікт у трикутнику і (Рис.10.4).
І на І-ому, і на ІІ-ому етапах елементарна дія алгоритму полягає у розв’язку сімейного конфлікту: якщо найбільший з синів більше, ніж батько, то переставляються батько і його син (процедура ConSwap).
У результаті перестановки може виникнути новий конфлікт в тому трикутнику, куди переставлений батько. Таким чином можна говорити про конфлікт (роду) у піддереві з коренем у вершині і. Конфлікт роду розв’язується послідовним розв’язком сімейних конфліктів – проходом по дереву зверху-вниз. (На Рис.10.5 шлях розв’язку конфлікту роду у вершині 2 відмічений.) Конфлікт роду розв’язаний, якщо прохід завершився (i > n div 2) або у результаті перестановки не виникнув новий сімейний конфлікт. (процедура Conflict)
Procedure ConSwap(i, j : Integer);
Var b : Real;
Begin
If a[i] < a[j]
then begin
b := a[i];
a[i] := a[j];
a[j] := b
end
End;
Procedure Conflict(i, k : Integer);
Var
j : Integer;
Begin
j := 2*i;
If j = k
then ConSwap(i, j)
else if j < k
then begin
if a[j+1] > a[j]
then j := j + 1;
ConSwap(i, j);
Conflict(j, k)
end
End;
I етап - побудови дерева, що сортує – оформимо в виді рекурсивної процедури, використовуючи визначення:
Якщо ліве і праве піддерева T(2i) і T(2i+1) дерева T(i) , що сортують, то для перебудови T(i) необхідно розрішити конфлікт роду в цьому дереві.
Procedure SortTree(i : Integer);
begin
If i <= n div 2
then begin
SortTree(2*i);
SortTree(2*i+1);
Conflict(i, n)
end
end;
На II-ому етапі - етапі просівання - для k от n до 2 повторюються наступні дії:
1.Переставити A[1] і A[k];
2.Побудувати дерево, що сортує початкового відрізка масиву A[1..k-1], усунувши конфлікт роду в корені A[1]. Відмітимо, що 2-а дія потребує введення в процедуру Conflict параметра k.
Program HeapSort;
Const
n = 100;
Var
A : Array[1..n] of real;
k : Integer;
{процедури ConSwap, Conflict, SortTree, введення, виведення}
Begin
{ введення }
SortTree(1);
For k := n downto 2 do begin
ConSwap(k, 1);
Conflict(1, k - 1)
end;
{ виведення }
End.