Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
proga_modul_otvety_na_terminy.docx
Скачиваний:
6
Добавлен:
17.07.2019
Размер:
49.5 Кб
Скачать

Рекурсивне означення, необхідні умови, яким має задовольняти множина об’єктів, що означаються рекурсивно

Означення називається рекурсивним, якщо воно задає елементи певної множини за допомогою інших елементів цієї ж множини. Об’єкт, заданий рекурсивним означенням, також називається рекурсивним, а використання таких означень — рекурсією.

З кожним рекурсивним викликом зайнята частина програмного стека збільшується, а з закінченням виклику — зменшується. Розмір стеку обмежений, тому можлива ситуація (особливо за виконання рекурсивних функцій), коли пам’яті в стеку забракне й програма завершиться аварійно.

У рекурсивній функції обов’язково має бути умова, за істинності якої відбувається повернення з виклику (див. приклади вище). Ця умова визначає «дно рекурсії», яке під час виконання функції обов’язково має досягатися, інакше виклики призведуть до переповнення програмного стека або інших непередбачуваних наслідків.

Глибина рекурсії, на якій перебуває виклик та породжена викликом

З рекурсивними функціями пов’язано два важливих поняття — глибина рекурсії та загальна кількість викликів, породжених викликом рекурсивної підпрограми. Будемо відрізняти глибину рекурсії, на якій перебуває виклик, і глибину рекурсії, породжену викликом.

Глибина рекурсії, на якій перебуває виклик підпрограми — це кількість рекурсивних викликів, розпочатих і незакінчених у момент початку цього виклику.

Глибина рекурсії, породжена викликом — це максимальна кількість рекурсивних викликів, які розпочато й не закінчено після початку цього виклику.

Наприклад, у програмі «Ханойські вежі» виклик функції tower з висотою h перебуває на глибині рекурсії nh та породжує глибину h‑1.

Коли виконується виклик функції, який перебуває на глибині рекурсії m, одночасно існує m+1 екземпляр локальної пам’яті функції. Кожен екземпляр займає ділянку певного розміру, тому збільшення глибини, як було сказано вище, може призвести до переповнення програмного стеку.

Загальна кількість рекурсивних викликів, породжених викликом.

Загальна кількість рекурсивних викликів, породжених викликом рекурсивної функції, — це кількість викликів, які виконано між його початком і завершенням.

Наприклад, у задачі «Ханойські вежі» кожен виклик задає одне перенесення диска та, якщо він не є найбільш заглибленим, породжує два рекурсивних виклики. Нам уже відомо, що перенесення вежі висотою n вимагає 2n‑1 перенесень дисків, тому між початком і закінченням виклику з аргументом n виконується 2n‑2 рекурсивних викликів.

Загальна кількість породжених викликів визначає тривалість виконання виклику. Як бачимо, кількість викликів у задачі «Ханойські вежі» за значень n уже порядку кількох десятків призводить до неприпустимо довгого виконання програми.

Записуючи рекурсивну функцію, необхідно уміти оцінити можливу глибину рекурсії, розмір пам’яті виклику функції та загальну кількість рекурсивних викликів.

Синтаксичне правило

Ще один приклад рекурсивних означень — це синтаксичні правила, які описують структуру виразів у різноманітних мовах.

В свій час було винайдено декілька форм запису синтаксичних правил. Найбільш поширені контекстно-вільні граматики Хомського (КВ-граматики) та їх різновиди — системи форм Бекуса-Наура (БНФ) та синтаксичні діаграми. Кожна з них дозволяє описати майже весь синтаксис мов програмування. Розглянемо синтаксичні правила у вигляді БНФ.

Надамо синтаксичним правилам чіткішу форму. Поняття мови позначимо словом у кутових дужках < >, наприклад, <вираз> або <ім’я>. Слова (лексеми) самої мови будемо записувати в 'апострофах' або виділяти напівжирним шрифтом, наприклад '=' або while. Порожню послідовність символів позначимо кутовими дужками < >.

Термінал, нетермінал, метавираз

Позначення поняття мови називається нетермінальним символом, або нетерміналом.

Термінальними символами, або терміналами, називаються символи або послідовності символів алфавіту мови. Термінали та нетермінали розглядаються як неподільні записи. “Термінальний” означає “остаточний” (термінали — “остаточні” символи мови). “Нетермінальний” (“неостаточний”) символ позначає поняття мови й не є символом самої мови.

Послідовність (можливо порожня), складена з терміналів, нетерміналів та певних спеціальних символів (метасимволів), називається метавиразом.

БНФ, система БНФ, семантика системи БНФ

Синтаксичне правило вигляду <поняття>::=<метавираз> називається формою Бекуса–Наура (за прізвищами авторів) або, скорочено, БНФ. Нетермінал ліворуч від метасимволу “::=” називається лівою частиною БНФ, або головою, метавираз праворуч — правою частиною, або тілом.

Отже, БНФ <вираз присвоювання> ::= <ім’я> '=' <вираз> задає загальну структуру кожного з конкретних виразів присвоювання. Структуру представників понять «вираз» та «ім’я» уточнимо за допомогою інших БНФ, які разом з наведеною БНФ утворять систему БНФ.

БНФ — це вираз, складений з терміналів, нетерміналів та метасимволів. БНФ має певну структуру — нетермінал, знак “::=”, метавираз. Семантикою системи БНФ є означення структури й множин представників понять, позначених нетерміналами. Мова БНФ використовується для опису синтаксису інших мов, тому називається метамовою.

послідовності терміналів та нетерміналів, вивідні з не терміналу

Усі вивідні послідовності терміналів називаються вивідними ланцюжками (словами мови). Вони є представниками головного поняття, а їх множина — формальною мовою, яку задає система БНФ.

Записи можна виводити з довільного нетермінала системи БНФ, а не лише з початкового, як у прикладі вище. Тоді одержуються представники відповідного поняття, наприклад конкретні вирази або імена: (B1+C0), (A01), A01.

формальна мова, відповідна не терміналу

семантика дужок (), [], {} у розширених БНФ. Доповнимо мову БНФ кількома зручними конструкціями. Для цього знадобиться ще одне поняття — еквівалентність БНФ.

Дві системи БНФ називаються еквівалентними, якщо задають одну й ту саму формальну мову.

Для коротшого й наочнішого запису еквівалентних БНФ в метавирази додають метасимволи (, ), [, ], {, }. Метавираз із такими символами називається розширеним, а БНФ — розширеною, або РБНФ. Розглянемо утворення РБНФ.

Нехай букви X, Y, Z, …, T позначають довільні метавирази (можливо, порожні), N — нетермінал.

1. Декілька альтернатив вигляду X Z Y | ... | X T Y у метавиразі, які мають спільні початок X та закінчення Y, можна замінити таким метавиразом.

X ( Z | ... | T ) Y

Метасимволи ( та ) тут просто відокремлюють частину метавиразу з альтернативами Z, …, T від інших частин.

Приклад. Правило

<вираз> ::= <ім’я> '+' <ім’я> | <ім’я> '-' <ім’я>

можна замінити еквівалентним.

<вираз> ::= <ім’я> ('+' | '-') <ім’я>

2. Замість двох альтернатив вигляду X Z Y | X Y можна записати такий еквівалентний вираз.

X [ Z ] Y

Приклад. Замість БНФ

<вираз> ::= <ім’я> | <ім’я> ('+'| '-') <ім’я>

запишемо таку.

<вираз> ::= <ім’я> [ ('+'| '-') <ім’я> ]

Аналогічно, замість БНФ

<інструкція_розгалуження> ::=

if '(' <умова> ')' <інструкція> |

if '(' <умова> ')' <інструкція> else <інструкція>

запишемо таку.

<інструкція_розгалуження> ::=

if '(' <умова> ')' <інструкція> [ else <інструкція> ]

3. Семантику метасимволів {, } означимо за допомогою прикладу.

Приклад. Ім’я, або ідентифікатор, у мовах програмування — це послідовність букв і цифр, що починається з букви. Нехай буквами є тільки A, B, C, цифрами — 0 і 1. Для імен вище було означено таку систему БНФ.

<ім’я> ::= <Б><ПБЦ>

<ПБЦ> ::= <> | (<Б> | <Ц>) <ПБЦ>

<Б> ::= 'A' | 'B' | 'C'

<Ц> ::= '0' | '1'

Узагальнимо букви й цифри поняттям “буква-цифра” з нетерміналом <БЦ>, додавши таке правило.

<БЦ> ::= <Б> | <Ц>

Тоді <ПБЦ> можна задати двома такими правилами.

<ПБЦ> ::= <> | <БЦ> <ПБЦ>

За допомогою цих правил із нетермінала <ПБЦ> можна вивести всі можливі послідовності <БЦ>:

<>, <БЦ>, <БЦ><БЦ>, ...,

і тільки їх. Позначимо множину послідовностей, складених з <БЦ>, метавиразом {<БЦ>} із новими метасимволами {, }. Будемо вважати, що всі послідовності <БЦ> вивідні з цього метавиразу. Тоді правилу

<ПБЦ> ::= {<БЦ>}

еквівалентні такі.

<ПБЦ> ::= <> | <БЦ> <ПБЦ>

Якщо X — довільний метавираз, то метавираз {X} позначає всі скінченні послідовності <>, X, XX, XXX, … . Дужки {} називаються ітераційними й підкреслюють ітеративну природу різного роду послідовностей.

Масив

У багатьох задачах у пам’яті програми треба зберігати великі набори однотипних даних. Для цього використовують масиви.

Масив — це змінна, утворена послідовністю змінних, які називаються елементами (компонентами), є однотипними й ідентифікуються номерами (індексами). Елементи масиву рівнодоступні — можливість їх обробки не залежить від їх місця в масиві.

Означення масиву має вигляд T a[n], де T — тип елементів, a — ім’я масиву, n — ціла константа, можливо, іменована. Константа задає розмір масиву. Елементи можуть мати довільний скалярний або структурний тип (масив та інші, про які йдеться в наступних главах). Індексами елементів є цілі числа від 0 до n-1.

Тип та кількість елементів масиву (його розмір) фіксується в означенні або під час створення й далі не змінюється.

елемент масиву

Елемент масиву ідентифікується іменем масиву та індексом. Наприклад, елемент масиву зі ста елементів, int a[100], позначається виразом вигляду a[IE], де вираз IE повинен мати ціле значення від 0 до 99.

рівнодоступність елементів масиву

індексна множина масиву

розмір масиву

що являє собою значення масиву з точки зору математики

ініціалізація масиву.

Значення, що ініціалізують послідовні елементи масиву, задаються списком констант у дужках {}, наприклад, int a[4]={2,10,3,15};. Якщо констант менше ніж елементів у масиві, вони присвоюються першим елементам масиву, а решта елементів отримують нульові значення відповідного типу. Наприклад, оголошення int cnt[4]={}; ініціалізує всі елементи значенням 0. Якщо ж констант більше ніж елементів масиву, то це є помилкою.

В ініціалізації можна не вказувати розмір масиву — він стає рівним кількості констант. Наприклад, оголошення int a[]={9,8,7}; задає масив з трьох елементів.

Елементи масиву, оголошеного без ініціалізації за межами функцій, в якості початкових значень отримують нулі відповідного типу, а масиву, оголошеного в тілі функції — випадкове «сміття».

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]