
- •Програмування
- •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. Заключне зауваження: переходимо до об’єктів
1.11. Блок - схеми
У старі добрі часи (50-60 роки ХХ століття), коли комп'ютери були великими і повільними, а мови програмування тільки починали формуватися, для представлення алгоритмів застосовували блок-схеми, а для реалізації алгоритмів у виді комп'ютерних програм – систему команд комп'ютера (машинний код).
Це робилося тому, що комп'ютерна програма в машинних кодах зовсім не пристосована для її читання. Ми вже розуміємо, що алгоритм потрібно спочатку винайти, а лише потім записати у формі, зрозумілій виконавцеві, тобто у виді машинного коду. В процесі винаходу алгоритму програмісти користувалися блок-схемами.
Блок-схема алгоритму – це його графічне зображення у виді декількох блоків, з'єднаних між собою стрілками. Блоки зображують команди алгоритму, а стрілки – послідовність виконання цих команд.
Команди, що описують обчислення (наприклад, команда присвоєння) зображуються у виді прямокутника
Рис 1.3. Блок Обчислення
Команда перевірки умови виглядає як ромб:
так
Рис 1.4. Блок Умова.
Початок і кінець алгоритму зображують у виді овалів:
Рис 1.5. Блоки Початок і Кінець.
Команди введення і виведення даних ми зобразимо так:
Рис 1.6. Блоки Введення і Виведення.
Існують і інші типи блоків, але ми ними користуватися не будемо.
1.12. Допоміжні алгоритми
Зобразимо зараз блок-схему алгоритму 1.1, а поруч – блок-схему алгоритму Евкліда 1.3.
Блоки, розташовані між блок-схемами алгоритму приклада 1.1 і алгоритму Евкліда, зображують “настроювання” алгоритму Евкліда на роботу з величинами алгоритму додавання дробів. Алгоритм додавання дробів відіграє роль основного алгоритму, а алгоритм Евкліда - допоміжного.
Рис 1.7 Основний алгоритм додавання дробів і допоміжний алгоритм Евкліда.
Вхідні величини допоміжного алгоритму перед тим, як він почне виконуватися, мають прийняти правильні значення. Після того, як допоміжний алгоритм обчислить значення вихідних величин, ці величини мають бути передані (повернуті) основному алгоритмові.
Вхідні і вихідні величини допоміжного алгоритму називають його параметрами. Формування значень параметрів у процесі взаємодії основного і допоміжного алгоритмів називають передачею параметрів.
Передачу параметрів у допоміжний алгоритм бере на себе Виконавець. Справа програміста – правильно указати фактичні значення цих параметрів в основному алгоритмі.
Ми показуємо блок-схемою зміст (тобто семантику) процесу взаємодії основного і допоміжного алгоритмів. У цьому і полягає головна перевага блок-схем: вони дозволяють представити процес виконання алгоритму в геометричних образах, істотно полегшуючи тим самим розуміння семантики алгоритму.
Алгоритм додавання дробів виконує команди послідовно. Якщо порівняти текст цього алгоритму з його блок-схемою, можна переконатися в тому, що особливих переваг у наочності зображення немає.
Пояснимо тепер на блок-схемах семантику команд розгалуження і повторення.
Команда Блок-схема
Поки
<
Умова
> вконати
<Команда>
Рис 1.8 Семантика команд управління
Блок-схема команди пояснює її виконання краще, ніж будь-який словесний опис.
Уявіть собі, однак, що Вам пропонують розглянути алгоритм, блок-схема якого зображена на рис 1.9.
Рис 1.9. Блок-схема алгоритму типу «спагетті».
Автор алгоритму при цьому стверджує, що його алгоритм працює правильно, тобто завжди вирішує поставлену задачу.
Чи легко Вам буде розібратися в лабіринті переходів між блоками, і перевірити логіку обчислень? Звичайно, ні. Кожна послідовність дій тут так вплетена в інші можливі послідовності, що все це разом узяте нагадує ретельно перемішані спагетті.
З технічної точки зору причина утворення спагетті полягає в тому, що блок Умова має два виходи, які, у принципі, можна направляти куди завгодно. Більш важливим є те, що у нашого гіпотетичного автора не все в порядку з логікою мислення. Він не зумів виділити головні і допоміжні способи управління обчисленнями, не зумів структурувати алгоритм. Наявність же блоку Умова з його двома виходами дозволяє деяким чином скомбінувати переходи замість того, щоб направляти процес побудови алгоритму по шляху визначення логічно обґрунтованої структури управління.
Розглянемо алгоритм рішення наступної задачі:
Приклад 1.6. Алгоритм наближеного розв’язання рівняння f(x) = 0 методом поділу відрізка навпіл.
У підручниках з обчислювальної математики цей метод розглядається як один з найбільш простих методів наближеного рішення рівнянь.
Дано:
Числовий
відрізок [a, b].
Функція
f(x), неперервна на відрізку і має на
цьому відрізку єдиний корінь x0.
t
– задана точність.
Знайти:
Корінь
x0
а
c
b
Метод:
Відрізок [a, b] розділимо навпіл точкою с. Визначимо, на якій з половин відрізка - [a, с] або [с, b] знаходиться шуканий корінь. (Оскільки функція f(x) неперервна і корінь x0 єдиний, на кінцях відрізка, що містить x0, функція f(x) приймає протилежні за знаком значення.) Поділ відрізка навпіл будемо продовжувати доти, поки його довжина не стане менше, ніж задана точність t. Тоді наближеним значенням x0 можна вибрати середню точку цього відрізка.
Розробляючи алгоритм, спочатку визначимо його вхід і вихід:
Алгоритм Рівняння;
Вхід
a, b, t: ДІЙСН;
Вихід
X0: ДІЙСН;
Початок
< послідовність команд алгоритму >
Кінець.
Ми уточнили імена вхідних і вихідних величин і визначили їх типи. Поставимо перед собою питання: який спосіб управління обчисленнями є головним? Виявляється, що це – послідовне виконання двох дій:
Початок
<Зменшити довжину відрізка до величини, меншої t>;
<Обчислити х0 як середину відрізка [a, b]>
Кінець.
Друга дія – це команда присвоєння x0 := (a+b)/2. Як можна уточнити першу дію? Це дія – повторення процедури поділу відрізка і вибору однієї з його половин. Цей спосіб описується командою повторення Поки <Умова> виконувати <Команда>. Тому потрібно визначити Умову і Команду.
Алгоритм Рівняння;
Вхід
a, b, t: ДІЙСН;
Вихід
X0: ДІЙСН;
Початок
Поки <довжина відрізка [a, b] більша або дорівнює t> виконати
(
<Знайти середину с відрізка [a, b];>
<Вибрати в якості відрізка [a, b] ту половину,
на якій розташований корінь>
);
x0 := (a+b)/2
Кінець.
Уточнюємо Умову і команду обчислення середини відрізка. Вводимо допоміжну величину с:
Алгоритм Рівняння;
Вхід
a, b, t: ДІЙСН;
Вихід
X0: ДІЙСН;
Доп
С: ДІЙСН;
Початок
Поки b –a >= t виконувати
(
с := (a+b)/2;
<Вибрати ту половину, на якій розташований корінь>
);
x0 := (a+b)/2
Кінець.
Уточнюємо дію вибору потрібної половини відрізку:
Алгоритм Рівняння;
Вхід
a, b, t: ДІЙСН;
Вихід
X0: ДІЙСН;
Доп
С: ДІЙСН;
Початок
Поки b –a >= t виконувати
(
с := (a+b)/2;
Якщо <f(a) і f(c) приймає протилежні за знаком значення>
то b := c
інакше a := c
);
x0 := (a+b)/2
Кінець.
Залишилося уточнити Умову:
Алгоритм Рівняння;
Вхід
a, b, t: ДІЙСН;
Вихід
X0: ДІЙСН;
Доп
С: ДІЙСН;
Початок
Поки b –a >= t виконувати
(
с := (a+b)/2;
Якщо f(a)*f(c)< 0
то b := c
інакше a := c
);
x0 := (a+b)/2
Кінець.
Розробляючи цей алгоритм, ми спиралися на його неформальний опис, викладений у виді методу рішення задачі. Програмування таких методів і є головною роботою програміста.
Після того, як метод знайдений і визнаний підходящим, програміст має описати його в системі команд виконавця, тобто закодувати. Методика, яку ми показали, називається методом послідовних уточнень .
Справді, ми почали з відповіді на таке питання: що дано і що потрібно знайти. Уточнення входу і виходу у виді описів величин – один з найважливіших етапів розробки алгоритмів.
Далі, на кожному кроці побудови алгоритму ми уточнювали одну з дій методу рішення задачі як команду або умову. Така дисципліна дозволяє обмежити міркування відповідями на такі питання:
Який спосіб управління потрібно зараз застосувати?
Чи можна реалізувати дію однією командою виконавця?
Як сформулювати умову?
Програміст, який усвідомлено застосовує метод послідовних уточнень, заощаджує свій час, радує начальство якістю і швидкістю роботи, допускає мало помилок і створює програми, які легко читати іншим програмістам.