Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
metod_lab_TA-2004-ukr.doc
Скачиваний:
1
Добавлен:
17.11.2019
Размер:
8.76 Mб
Скачать

З метою поліпшення можна прийти до питання, а чи потрібна перевірка

a[m] !=x.

Що, якщо надати таке рішення:

і помістити перевірку за виходом із циклу.

L=0; R=N-1; m=0;

while(L<=R)

{ m=(L+R)/2;

if(a[m]==x) i=m, break;

else if(a[m]<x) L=m+1;

else R=m-1;

}

if(a[R]!=x) немає елемента;

Необхідно довести, що умова L>=R досяжна (тобто обидві секції пошуку "накриють" масив цілком).

Для доказу необхідно показати, що RL убуває:

  • спочатку L<R

  • а потім або L зростає (m+1), або R зменшується.

Інтерполяційний пошук.

Якщо відомо, що К знаходиться між К1 і Кр, то номер чергового елемента для порівняння визначається формулою:

Прямий пошук рядка

Задано char S[N] і p[M], де 0<M<=N. Пошук рядка полягає у виявленні першого входження P у S.

Будемо вважати результатом індекс i, що вказує на перше входження у S. Уведемо предикат:

Звідси, якщо шукати розбіжність між образом і рядком, можна записати:

Тоді програмна реалізація прийме вигляд:

i=-1;

do

{ i++; j=0;//Q(i)

while(j<M&&S[i+j]=P[j])

{j++;}

} while(j!=M|| i=!(N-M));

j=M – умова "знайдена"

!(N-M)– збіг у рядку не виявлено

Алгоритм ефективний тільки у випадку, якщо збіг буде досягнуто після декількох порівнянь у внутрішньому циклі. Інакше, щоб знайти збіг наприкінці рядка, буде потрібно порівнянь.

Пошук у рядку (алгоритм Кнута, Моріса, Пратта)

i=0; j=0;

while(j<M && i<N)

{while(j>=0&& s[i] !=P[j])

{j=d;}

i++; j=j+d; //

}

1.3 Варіанти індивідуальних завдань до лабораторної роботи 1

  1. Пошук елемента серед введених цілих чисел методом половинного розподілу.

  2. Пошук елемента серед генерованих через RND чисел методом половинного розподілу.

  3. Пошук підрядка в рядку. Організувати через масиви.

  4. Пошук заданого елемента серед генерованих через RND чисел методом половинного розподілу. Для створення масиву скористатися покажчиками.

  5. Пошук символу в рядку.

  6. Реалізувати метод інтерполяційного пошуку.

  7. Порівняти "швидкість" пошуку в методах половинного розподілу та інтерполяційного пошуку.

  8. Пошук рядка в рядку. Організувати через покажчики.

  9. Написати функцію, що дозволяє знаходити символ у рядку.

  10. У заданій послідовності поміняти місцями перший від’ємний елемент, що зустрівся, з першим додатним елементом, що зустрівся за ним.

  11. Визначити, скільки разів у сформованому вами рядку зустрічається сполучення символів "a" і "b". Символи "a" і "b" задаються в інтерактивному режимі.

  12. Визначити, скільки разів у сформованому вами рядку повторюються обрані символи, з яких складається алфавіт.

  13. Визначити, скільки разів у вашому рядку зустрічається кожний із символів, і яке сполучення з цих символів найбільш часто зустрічається.

  14. Визначити, скільки однотипних сполучень символів міститься в переліку прізвищ студентів, сформованих у попередньому завданні.

  15. Скласти програму визначення слів, що містять цифрові символи.

  16. Виділити частину рядка, розташованого між двома буквами. Букви виводяться за запитом.

  17. У довільно взятій пропозиції віддрукувати слова, в яких збігається більше двох букв.

  18. Віддрукувати слово тексту з максимальною кількістю голосних букв.

  19. Вивести на друк рядок символів, розташованих в дужках.

  20. Визначити кількість слів, що складають дану пропозицію.

  21. Дано довільний рядок, що містить 10 слів. Потрібно надрукувати цю послідовність слів, але в зворотному порядку.

  22. Дано довільний рядок, що містить 10 слів. Потрібно надрукувати всі слова, перед якими в послідовності знаходяться тільки менші (за алфавітом) слова, а за ними – більші.

  23. Дано довільний рядок, що містить 10 слів. Потрібно надрукувати всі слова, що у послідовності зустрічаються по одному разу.

  24. Дано довільний рядок, що містить 10 слів. Потрібно надрукувати всі слова за абеткою.

  25. Дано довільний рядок, що містить 10 слів. Потрібно надрукувати всі різні слова, вказавши для кожного з них число його входжень у послідовність.

  26. У довільно сформованому рядку, що містить 60 латинських букв, потрібно всі входження Lat замінити на Tal.

  27. У довільно сформованому рядку, що містить 60 латинських букв, потрібно видалити перше входження AD , якщо таке є, а їх місце заповнити наступними буквами; наприкінці додати пробіли.

  28. Скласти функцію, що дозволяє визначити позицію самого правого входження заданого символу у вихідний рядок. Якщо рядок не містить символу, результатом роботи процедури повинна бути –1.

  29. Задано дві послідовності цілих чисел і число k. Якщо в послідовності немає жодного члена зі значенням k, тоді перший член цієї послідовності, не менший від усіх інших членів, замінити на значення k. Так само перетворити відносно до значення 10.

  30. Скласти функцію перестановки кожної пари елементів масиву (перший і другий, третій і четвертий і т.д.). Застосувати її для векторів MX[10], MY[8], MZ[6].

1.4 Контрольні запитання та завдання

1. Які основні відмінності Ви бачите в методах лінійного пошуку й пошуку розподілу навпіл?

  1. Що лежить в основі оптимізації методу пошуку розподілу навпіл?

  2. Коли ефективний алгоритм методу пошуку прямого рядка?

  3. Визначити основні вимоги до алгоритму прямого пошуку в рядку.

2 РОЗВ’ЯЗАННЯ ЗАДАЧ З ВИКОРИСТАННЯМ РЕКУРСІЇ

2.1 Мета роботи

Освоєння методів розв’язання задач з використанням рекурсії.

2.2 Підготовка до роботи

Під час підготовки до роботи слід вивчити методи [1, с. 75-90; 2, с. 89-96].

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

Обчислювані функції – це такі функції значення, які можна встановити за допомогою деякого алгоритму. Функція називається рекурсивною, якщо існує ефективна процедура для її обчислення.

Поняття ефективної процедури є інтуїтивним, і говорять, що існує процедура для виконання визначених обчислень, якщо ці обчислення виробляються за визначеними правилами (алгоритму).

Сукупність числових функцій, що співпадає із сукупністю всіх обчислювальних функцій при самому широкому, дотепер відомому розумінні алгорит­му, називаються рекурсивними функціями.

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

Черч (виходячи з інших передумов), вивів той же клас числових функцій, що і Гедель, і сформулював гіпотезу, що клас рекурсивних функцій тотожний із класом всюди визначених обчислювальних функцій. Поняття обчислювальної функції точно не визначається, тому тезу Черча довести не можна.

Якщо деяким елементам Х поставлені у відповідність деякі елементи Y, то говорять, що задано часткову функцію з Х в Y. (Якщо область визначення Х в Y збігається з безліччю Х, то функція називається всюди визначеною).

Кліні ввів поняття частково рекурсивної функції і висунув гіпотезу, – "всі частково рекурсивні функції, обчислені за допомогою алгоритмів, є частково рекурсивними".

(Далі цілочислові і цілозначимі функції називаються арифметичними.)

У теорії рекурсивних функцій велике значення мають три операції:

операція суперпозиції функцій полягає в підстановці одних арифметичних функцій замість аргументів інших арифметичних функцій;

операція примітивної рекурсії дозволяє будувати місцеву арифметичну функцію (функцію від перемінних) по двох заданих функціях -місцевої і місцевої функції;

операція найменшого кореня чи операція мінімізації дозволяє визначити нову арифметичну функцію від перемінних за допомогою раніше побудованої арифметичної функції від перемінних.

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

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

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

Які б класи точно обкреслених алгоритмів дотепер не будувалися, у всіх випадках незмінно виявлялося, що числові функції, які обчислюються за допомогою алгоритмів цих класів, були частково рекурсивними (Теза Черча).

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

Значна кількість задач розв’язується з використанням алгоритмів, засно- ваних на використанні рекурсивних функцій. Але слід знати, що не всі задачі, що можуть бути вирішені з використанням рекурсивних функцій, виграють у порівнянні з ітераційними алгоритмами. Навіть навпаки, якщо задача може мати розв’язання, засноване на використанні ітераційних алгоритмів, то воно краще. Цей висновок базується на аналізі втрат часу, зв'язаних з викликом функцій.

Прикладом виправданого використання рекурсії може служити розв’язання задачі щодо Ханойських веж.

Ця задача формулюється в такий спосіб: дано три стрижні. На одному з них знаходяться диски різних розмірів, зменшені до верху (піраміда). Потрібно перенести ці диски на інший стрижень, використовуючи тільки один, допоміжний стрижень. При цьому за один раз можна перенести тільки один диск, а більший за розміром диск неприпустимо ставити на диск меншого розміру.

Доказ розв’язання цієї задачі засновано на використанні індукційного методу, з якого безпосередньо випливає алгоритм, який діє на використанні рекурсивних функцій. Так, у випадку з одним диском, він просто перекладається з вихідного стрижня на заданий. У випадку з двома дисками спочатку верхній диск перекладається на допоміжний стрижень, а потім нижній диск із вихідного стрижня і верхній з допоміжного стрижня перекладаються на заданий. Аналогічно, якщо є дисків, спочатку дисків при дотриманні правил перестановки переміщаються на допоміжний стрижень, а потім на заданий стрижень переноситься нижній диск (він знайшов своє місце). Далі, з огляду на те, що останній диск, переміщений на заданий стрижень, ніяк не заважає, оскільки він більший за всі інші, задача розв’язується аналогічно. Виключення полягає в тому, що диск із тих, що залишилися, використовуючи в якості проміжного заданий, переміщається на допоміжний, котрий раніше був вихідним, а останній, що залишився, знову переміщається на заданий стрижень. Таким чином, після двох циклів перестановок, ми приходимо до вихідної ситуації використання стрижнів, але кількість дисків, які необхідно переставити менше на два диски і т.д.. Процес рекурсії зупиняється, коли залишається тільки один диск, що переміщається на заданий. Доведено, що для n дисків мінімальне число необхідних переміщень дорівнює .

Рекурсивна функція має завжди визначати умову закінчення, інакше рекурсія стане нескінченою.

#include<iostream.h>

int k;

void Hanoy1 (char a,char b,char c,int n );

void main()

{

cout<<"введіть кількість дисків"<< "\n";

cin>>k;

Hanoy1 ('A', 'C', 'B', k);//перенесено k дисків з A на C, проміжний B

cin>>k;

}

void Hanoy1 (char a,char b,char c,int n )

{int v;

v=n;

if (n==1)

cout<<"перемістити "<< v<<" з "<< a<<" на "<<b<<"\n";

else

{Hanoy1 (a, c, b, n - 1); //перенесено n - 1 дисків з A на C, проміжний B

cout<<"перемістити "<<v<<" з "<< a<<" на "<< b<<"\n";

Hanoy1 (c, b, a, n - 1); // перенесено n - 1 дисків з C на B, проміжний A

} }

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