
Methods_AP_PZ
.pdf
7. Переглянути (витягти) елемент, що знаходиться у зазначеній позиції списку.
Так виглядає список у середовищі моделювання Rational Rose.
Стеком називається виділена (програмістом) область ОЗП, для якої програмно організовані спеціальні режими функціонування:
- магазинний з дисципліною обслуговування "першим прийшов - останнім вийшов" (FILO - first in, last out), або - кільцевий з дисципліною "першим прийшов - першим вийшов" (FIFO - first in, first out).
Магазинний стек з дисципліною FILO
Магазинний стек з дисципліною FILO «першим прийшов - останнім вийшов» являє собою одномірну структуру з N виділених в ОЗУ під стек комірок пам’яті і одного покажчика W для вказівки комірки пам’яті, що є вершиною стека.
На логічному рівні робота стека FILO організована так, що операція запису-читання в / з стека завжди адресується до однієї і тієї ж комірки пам'яті - вершині стека W - і супроводжується для збереження попередньої інформації одночасним (паралельним) переносом (витісненням) вмісту молодших комірок пам'яті в старші при записі і навпаки зі старших в молодші при читанні.
Кільцевій стек з дисципліною FIFO
Кільцевій стек з дисципліною FIFO (першим прийшов - першим вийшов) являє собою одномірну структуру з N виділених під стек КП і двох покажчиків: F (first) - для вказівки КП, що містить перші з записаних в стек
41
даних, і L (last) - для вказівки КП, що містить останні з записаних в стек даних (в порядку надходження останніх).
Для запису чергових даних в стек достатньо виконати інкремент покажчика L і занести ці дані в комірку пам'яті, на яку буде показувати L, а
для читання - вивести вміст комірки пам'яті, на яку показує покажчик F, і
потім виконати інкремент F, щоб забезпечити читання наступних даних.
Приклад 6.1
Алгоритм «Дужки». Виконує синтаксичний аналіз послідовності дужок на правильність побудови. Метод програмування - стек з дисципліною обслуговування «першим прийшов - останнім вийшов» (FILO). Опишемо алгоритм за допомогою псевдокоду.
ВХ.ДАНІ: <(>: = -1, <)>: = +1, <[>: = -2, <]>: = +2 і т.д. <Кінець послідовності>: = 0
Крок 1. Введення послідовності
X, S: array [1 .. 30] of integer
I = 0; X (I) = 1
while X (I) <> 0 do I = I + 1; read X (I) od
[Запам'ятати довжину послідовності і ініціалізувати стек]
N = I - 1; I = 1; W = 0
Крок 2. Аналіз послідовності while I <= N do
[Узяти X (i) та якщо це лівий символ, записати його в стек] if X (I) <0 then
W = W + 1; S (W) = X (I)
else [узяти S (w) і якщо це лівий партнер X (i) видалити зі стека] if | S (W) | = X (I) then
W = W - 1 else
42
print <Синтаксична помилка>; goto 4 fi
fi
I = I + 1 [перейти до наступного символу] od
Крок 3. Перевірка: після перегляду послідовності стек порожній? if W = 0 then
write <Правильно побудована послідовність> else
write <Синтаксична помилка > fi
Крок 4. Кінець
End.
6.2 Завдання на практичну роботу
Виконати завдання згідно вказівок викладача.
1.Перетворіть у постфіксной вираз (5 * ((9 * 8) + (7 * (4 + б)))).
2.Напишіть програму, яка з використанням стека магазинного типу перетворить постфіксной вираз в інфіксний.
3.Реалізуйте компілятор і інтерпретатор для мови програмування, в
якому кожна програма складається з одного арифметичного виразу. Вислову передує ряд операторів присвоювання з арифметичними виразами, що складаються з цілих чисел і змінних, що позначаються одиночними
символами нижнього регістра. Наприклад, отримавши вхідні дані
(Х = 1)
(У = (х + 1))
(((Х + у) * 3) + (4 * х))
програма повинна вивести число 13.
43
4. Припустимо, що ви змінюєте інтерфейс стека магазинного типу,
замінюючи операцію перевірки, чи порожній стек, операцією підрахунку, яка повертає кількість елементів, що знаходяться в даний момент в структурі даних. Реалізуйте операцію підрахунку для представлення на базі масиву.
5.Напишіть реалізацію стека магазинного типу на базі зв'язного списку,
вякій елементи списку зберігаються починаючи з першого занесеного елемента і завершуючи останнім занесеним елементом. Потрібно використовувати двохзв'язний список.
6.Розробіть АТД, який містить два різних стека магазинного типу.
Скористайтеся реалізацією на базі масиву. Один стек розташуєте на початку масиву, інший - в кінці. (Якщо клієнтська програма працює так, що один стек збільшується, в той час як інший зменшується, ця реалізація буде займати менший обсяг, ніж альтернативні варіанти).
7. Реалізуйте функцію обчислення інфіксних виразів, що складаються з цілих чисел, буде потрібно розглянути випадок, коли обидва стека містять елементи одного і того ж типу.
8.У послідовності EAS * Y * QUE *** ST *** IO * N *** буква означає операцію put, а зірочка - операцію get. Знайдіть послідовність значень, що повертаються операціями get, коли ця послідовність операцій виконується над спочатку порожній чергою FIFO.
9.У послідовності EAs + Y + QUE ** + st + * + IO * n + + *
буква верхнього регістру означає операцію put на початку дека, буква нижнього регістра - операцію put в кінці дека, знак плюс означає операцію get на початку, а зірочка - операцію get в кінці. Знайдіть послідовність значень, що повертаються операціями get, коли ця послідовність операцій виконується над спочатку порожнім деком.
10.Запишіть інтерфейс для АТД "Дек".
11.Для інтерфейсу дека з попереднього завдання запишіть реалізацію, в
якій в якості базової структури даних використовується масив.
44
12.Для інтерфейсу дека (завдання 11) запишіть реалізацію, в якій в якості базової структури даних використовується двохзв'язной список.
13.Створіть АТД "Неупорядкована черга" (напишіть інтерфейс і реалізацію), в якому в якості базової структури даних використовується масив. Забезпечте для кожної операції постійний час виконання.
14.Створіть АТД "Неупорядкована чергу" (напишіть інтерфейс і реалізацію), в якому в якості базової структури даних використовується зв'язний список.
15.Напишіть програму-клієнт, яка вибирає для лотереї числа наступним чином: заносить в невпорядковану чергу числа від 1 до 99, а потім видаляє п'ять з них і виводить результат.
16.Напишіть програму-клієнт, яка зчитує з командного рядка в якості першого аргументу ціле число N, а потім роздруковує результат роздачі в покері карт на N гравців. Для цього вона повинна заносити у невпорядковану чергу N елементів і потім видавати результат вибору з цієї черги п'яти карт за один раз.
17.Напишіть програму, яка вирішує задачу зв'язності. Для цього вона повинна вставляти всі пари в невпорядковану чергу, а потім за допомогою алгоритму зваженого швидкого пошуку витягує їх з черги.
18.Реалізуйте операцію підрахунку з завдання 4 для представлення на базі зв'язного списку.
19.Напишіть реалізацію абстрактного списку, використовуючи динамічний масив.
20.Користуючись покажчиками, напишіть реалізацію списку,
відкритого з двох сторін, в якому вставка і видалення відбуваються з обох кінців.
а) не користуйтеся покажчиком на хвіст списку;
б) користуйтеся покажчиком на хвіст списку.
45

21. Для абстрактного списку символів знайдіть індекс найлівішого входження заданого символу в рядок; визначте, чи є один рядок підрядком іншого рядка.
22. Проаналізуйте розріджену реалізацію абстрактного полінома, в якій зберігаються лише коефіцієнти при ненульових елементах. Визначте операцію обходу розрідженого полінома, що дозволяє складати два розріджених полінома, ігноруючи члени з нульовими коефіцієнтами.
23. Граючи в настільні ігри або користуючись спільними комп'ютерними ресурсами, ви стаєте в чергу і чекаєте, коли настане ваша. Кількість гравців,
що беруть участь в грі, практично постійна, в той же час кількість користувачів комп'ютерних ресурсів часто змінюється. Будемо припускати,
що ці зміни носять постійний характер. Розробіть абстрактний тип даних,
призначений для відстеження черг. Передбачте операції вставки і видалення елементів черги, а також спосіб визначення, чия черга настала в даний момент. Програма повинна виконати декілька операцій вставки і видалення,
гарантуючи правильну черговість.
24. Іноді буває корисним реалізувати пов'язані структури, не користуючись покажчиками. Одна з таких структур використовує масив,
елементи якого «пов'язані» з допомогою індексів. На малюнку (а) показаний масив вузлів пов'язаного списку. Кожен вузол складається з двох членів, item
та next. Член next - це цілочисельний індекс елемента масиву, що містить наступний вузол пов'язаного списку. Член next останнього вузла дорівнює -
1. Цілочисельна змінна head містить індекс першого вузла списку. Елементи масиву, які в даний момент не є вузлами пов'язаного списку, утворюють
вільний список (free list) доступних вузлів. Ці вузли утворюють інший
46

зв'язаний список. Індекс першого вільного вузла міститься в цілочисельний змінної free. Щоб вставити елемент в вихідний зв'язаний список, потрібно витягти вузол з початку вільного списку і вставити його в даний зв'язаний список (б). Щоб видалити елемент із зв'язаного списку, потрібно вставити його в початок вільного списку (в). Це дозволяє не зрушувати елементи масиву. Реалізуйте абстрактний список у вигляді масиву, що містить вузли пов'язаного списку.
25. Напишіть програму, що реалізовує інвентарну відомість. Передбачте можливість роботи з декількома інвентарними відомостями.
47

Практична робота № 7
Динамічне програмування та рекурсія
7.1 Теоретичні відомості
Основна ідея динамічного програмування полягає у виключенні повторних обчислень вже отриманих раніше результатів.
Приклад 7.1
На рисунку зображений трикутник з чисел. Напишіть програму, яка обчислює найбільшу суму чисел, розташованих на шляху, що починається у верхній точці трикутника і закінчується на основі трикутника.
Кожен крок на шляху може здійснюватися вниз по діагоналі вліво або вниз по діагоналі вправо.
Число рядків в трикутнику> 1 і <100.
Трикутник складений з цілих чисел від 0 до 99.
Розглянемо наступну ідею рішення.
Вхідні дані запишемо в матрицю D.
Будемо обчислювати матрицю R: array [l .. MaxN, O.. MaxN] наступним чином, попередньо обнуливши її елементи. Фрагмент програми на псевдокоді.
Крок 1. R[1,1]=D[1,1] For i=2 To N Do
Крок 2. For j=l То i Do R[i,j ]=max(D[i,j ]+R[i-l,j ] D[i,j]+R[i-l,j-l])
де mах - функція обчислення максимального з двох чисел.
Залишилося знайти найбільше значення в останньому рядку матриці R,
воно дорівнює 30.
48
Приклад 7.2
У рекурсивній програмі, де при кожній ітерації циклу кількість вводів зменшується на одиницю, виникає наступне рекурентне співвідношення:
CN = CN-1 + N, де N ≥ 2 і C1 = 1.
Розв’язання. CN порядка N2/ 2. Для вирішення рекурсії її можна розкрити, застосовуючи саму до себе таким чином:
CN = CN-1 + N
=CN-2 + (N-1)+N
=CN-3 + (N-2)+(N-1)+N
Продовжуючи таким же чином, можна отримати
CN = C1 + 2 + ... + (N- 2) + (N- 1) + N
=1 + 2 + ... + (N- 2) + (N - 1) + N
=N(N + 1) /2.
Підрахунок суми 1 + 2 + ... + (N - 2) + (N - 1) + N елементарний: додамо до суми її ж, але в зворотному порядку. Результуюча сума - подвоєний шуканий результат - буде складатися з N доданків, кожне з яких дорівнює N
+ 1.
Приклад 7.3
У рекурсивній програмі, де на кожному кроці кількість вводів зменшується вдвічі, виникає наступне рекурентне співвідношення:
CN= СN/2 + 1, де N ≥ 2 і C1= 1.
Розв’язання. CN порядка lg N. написаного випливає, що це рівняння безглуздо за винятком випадку, коли N парне або ж передбачається, що N / 2
- цілочисельне ділення Зараз припустимо, що N = 2n, щоб рекурсія була завжди визначена. (Зауважте, що n = lg N.) Тоді рекурсію ще простіше розкрити, ніж у попередньому випадку:
49
C2n C2n 1 1
C2n 2 1 1
C2n 3 3
.
.
.
C20 n n 1
Точне розв’язання для будь-якого N залежить від інтерпретації N/2.
Якщо N/2 представляє собой [N/2], тоді існує дуже просте розв’язання: CN —
це кількість біт в двійковому представленні числа N, тобто за визначенням
[lg N] + 1. Цей висновок негайно випливає з того, що операція відкидання правого біта в двійковому поданні будь-якого числа N ≥ 0 перетворює його в
[N/2].
N |
(N ) |
2 |
|
lg N |
|
1 |
|
|
|
|
|
|
|
1 |
1 |
|
|
1 |
|
|
|
|
|
|
|
||
2 |
10 |
|
2 |
|
||
|
|
|
|
|
||
3 |
11 |
|
2 |
|
||
|
|
|
|
|
||
4 |
100 |
|
3 |
|
||
|
|
|
|
|
||
5 |
101 |
|
3 |
|
||
|
|
|
|
|
||
6 |
110 |
|
3 |
|
||
|
|
|
|
|
||
7 |
111 |
|
3 |
|
||
|
|
|
|
|
||
8 |
1000 |
|
4 |
|
||
|
|
|
|
|
||
9 |
1001 |
|
4 |
|
||
|
|
|
|
|
||
10 |
1010 |
|
4 |
|
||
|
|
|
|
|
||
11 |
1011 |
|
4 |
|
||
|
|
|
|
|
||
12 |
1100 |
|
4 |
|
||
|
|
|
|
|
||
13 |
1101 |
|
4 |
|
||
|
|
|
|
|
||
14 |
1110 |
|
4 |
|
||
|
|
|
|
|
||
15 |
1111 |
|
4 |
|
||
|
|
|
|
|
|
|
50