
- •Програмування
- •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. Заключне зауваження: переходимо до об’єктів
14.5. Проектування модулів. Модуль rat
Модуль RAT містить всі засоби, що забезпечують застосування у програмах раціональних чисел. Сюди входять:
описання типу Rational, констант типу Rational;
процедури введення-виведення раціональних чисел;
функції перетворення числових типів і типу Rational;
функції арифметичних операцій і порівнянь раціональних чисел;
засоби, що використовуються для реалізації вищевказаних процедур (внутрішні засоби модуля).
Проектування почнемо з визначення поняття раціонального числа. Раціональні числа – це дроби виду Num/Den, де Num – чисельник, а Den – знаменник. Для забезпечення коректності і єдності представлення раціонального числа у виді пари <Num, Den> (дробу Num/Den) нехай виконуються наступні обмеження:
Den > 0, НОД(Num, Den) = 1, Якщо Num = 0, то Den = 1
Таке представлення ми будемо називати канонічною формою. Дії над дробами природно і зручно реалізовувати у виді функцій. Але функції мови Pascal повертають скалярні значення. Тому представлення дробу у виді запису у цьому випадку непридатне. Для того, щоб обійти цю чисто лінгвістичну перешкоду, уточнимо тип Rational як посилання на запис:
Type
Rational = ^RatValue;
RatValue = Record
Num, {чисельник }
Den: LongInt {знаменник}
End;
{Тип LongInt - один із цілочисельних типів в TP-6. Множина значень визначена константою MaxLongInt = 231 - 1.}
Нижче описані деякі (далеко не всі) засоби RAT, необхідні для роботи з раціональними числами. Ключовою функцією модуля є функція CanRat, що приводить дріб до канонічної форми. У свою чергу, CanRat використовує цілочисельну функцію GCD, яка обчислює найбільший спільний дільник (НСД) двох натуральних чисел.
A / B = A div НСД(А, В) / В div НСД(А, В)
{------------НСД двох натуральних чисел-------------------------}
Function GCD(u, v: LongInt): LongInt;
Begin
While (u <> 0) and (v <> 0) do
If u > v
then u := u mod v
else v := v mod u;
If u = 0
then GCD := v
else GCD := u
End;
{------------канонізація раціонального числа--------------------}
Function CanRat(X: Rational): Rational;
Var
u, v, w: LongInt;
Begin
u := X^.Num;
v := X^.Den;
If v = 0
then CanRat := Nil {дріб із нульовим знаменником}
else begin
If v < 0 {знаменник > 0}
then begin
u := -u;
v := -v end;
w := GCD(Abs(u), v);
If w <> 1
then begin {скорочення чисельника і знаменника}
u := u div w;
v := v div w end;
New(R);
Z^.Num := u;
Z^.Den := v ;
CanRat := Z;
end
End;
Як уже відзначалось, процедури введення-виведення потребують дуже старанного проектування, що враховує багато факторів (зручність використання, захист від несанкціонованих дій і т.д.). Ми опишемо тільки їх тривіальні макети.
{ВВЕДЕННЯ-ВИВЕДЕННЯ}
Procedure RatInp(var X: Rational); {Введення}
Var
Ch: Char;
Begin
New(X);
Write('введення чисельника '); Read(X^.Num);
Ch := ReadKey;
If Ch = '/'
then begin
Write('введення знаменника '); Read(X^.Den);
X := CanRat(X)
end
else X^.Den := 1
End;
Procedure RatPrint(X: Rational); {Виведення}
Begin
If X = Nil
then Write('Ділення на нуль')
else begin
Write(X^.Num);
If X^.Den <> 1
then begin Write('/'); Write(X^.Den) end;
end;
Writeln
End;
{АРИФМЕТИЧНІ ОПЕРАЦІЇ}
Function AddRat(X, Y: Rational): Rational; {Додавання}
Begin
New(Z);
Z^.Num := X^.Num*Y^.Den + X^.Den*Y^.Num;
Z^.Den := X^.Den*Y^.Den;
AddRat := CanRat(Z)
End;
Function SubRat(X, Y: Rational): Rational; {Віднімання}
Begin
New(Z);
Z^.Num := X^.Num*Y^.Den - X^.Den*Y^.Num;
Z^.Den := X^.Den*Y^.Den;
SubRat := CanRat(Z)
End;
Function MultRat(X, Y: Rational): Rational; {Множення}
Begin
New(Z);
Z^.Num := X^.Num*Y^.Num;
Z^.Den := X^.Den*Y^.Den;
MultRat := CanRat(Z)
End;
Function DivRat(X, Y: Rational): Rational; {Ділення}
Begin
If Y^.Num = 0
then DivRat := Nil
else begin
New(Z);
Z^.Num := X^.Num*Y^.Den;
Z^.Den := X^.Den*Y^.Num;
DivRat := CanRat(Z)
end
End;
Function MinusRat(X: Rational): Rational; {число з знаком мінус}
Begin
New(Z);
Z^.Num := -X^.Num;
Z^.Den := X^.Den;
MinusRat := Z
End;
{ПОРІВНЯННЯ}
Function EquRat(X, Y: Rational): Boolean; {Рівність}
Begin
EquRat := (X^.Num = Y^.Num) and (X^.Den = Y^.Den)
End;
Function GrtRat(X, Y: Rational): Boolean; {Порівняння на "більш"}
Begin
GrtRat := SubRat(X, Y)^.Num > 0
End;
{ПЕРЕТВОРЕННЯ ТИПІВ}
Function RatReal(X:Rational): Real; {Раціональні в дійсні}
Begin
RatReal := X^.Num/X^.Den
End;
Function IntRat(X: LongInt): Rational; {Ціле в раціональне}
Begin
New(Z);
Z^.Num := X; Z^.Den := 1;
IntRat := Z
End;
Кожна з функцій, що описані вище, реалізує одну з дій у відповідності з його математичним визначенням. Так, наприклад, додавання спирається на формулу
A/B + C/D = CanRat((A*D + B*C)/(B*D))
Оскільки модуль планується використовувати при програмуванні багатьох прикладних задач, особливу увагу треба приділити його оптимізації. З цією метою необхідно, в першу чергу, виділити і оптимізувати ключеві засоби модуля. У нашому прикладі це функції GCD і CanRat.
Ще один шлях підвищення ефективності – зменшення середньої кількості викликів функції CanRat у функціях модуля. У функції AddRat, наприклад, це можна зробити, розглянувши поряд з загальною формулою додавання її окремі випадки, в яких виклик CanRat не потрібний. Попутно зменшується і кількість арифметичних операцій. На справді, при визначенні додавання виділимо окремі випадки додавання дробу і цілого числа, а також дробів з рівними знаменниками
A/B + C/D = CanRat((A*D + B*C)/(B*D)); (*)
A/B + C/B = CanRat((A + C)/B);
A/B + C = (A + B*C)/B;
A + C/D = (A*D + C)/D
Функція AddRat, що реалізована у відповідності з цим визначенням, у середньому ефективніше, ніж описана у модулі.