Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Зубенко, Омельчук - Програмування. Поглиблений курс

.pdf
Скачиваний:
58
Добавлен:
07.03.2016
Размер:
5 Мб
Скачать
☆

Розділ IV. АЛГОРИТМИ

Стандартні узагальнені алгоритми. У стандартній бібліотеці ша-

блонів STL визначені узагальнені алгоритми для роботи з контейнер- ними типами (табл. 4.1). Для використання алгоритмів, що не зміню- ють елементів послідовності модифікуючих і сортувальних алгорит- мів, у програму потрібно ввести заголовний файл <algorithm>, а для обчислювальних алгоритмів – заголовний файл <numeric> (табл. 4.2).

Усі алгоритми реалізовані як шаблони функцій (див. підрозд. 3.12) і обробляють вхідну послідовність елементів контейнера, задану парою ітераторів [first, last) (останнім елементом, що обробляється, є last-1). Багато алгоритмів реалізовано в кількох варіантах, для різних наборів параметрів, тому тут наведені лише їхні назви. Деякі з пере- лічених тут алгоритмів уже згадувалися вище.

Таблиця 4.1. Алгоритми, визначені в <algorithm>

Функція

 

Призначення

 

 

adjacent_find

Пошук першої пари збіжних елементів

 

binary_search

Перевірка входження заданого елемента в упо-

Copy

рядкований інтервал

 

 

Копіювання вхідного інтервалу в новий контейнер

copy_backward

Копіювання вхідного інтервалу в новий кон-

count

тейнер у оберненому порядку

 

 

Підрахунок кількості елементів у інтервалі

 

count_if

Підрахунок кількості елементів у інтервалі, що

equal

відповідає заданому предикату

 

Бінарний пошук у інтервалі інтервалу елемен-

equal_range

тів, що дорівнюють заданому елементу

 

Бінарний пошук у впорядкованому інтервалі ін-

 

тервалу елементів, що дорівнюють заданому еле-

fill

менту

 

 

 

Заповнює інтервал заданим значенням

 

fill_n

Заповнює

контейнер,

починаючи

з

find

n-го елемента, заданим значенням

 

Заповнює перші n елементів заданим значен-

find_end

ням

 

 

 

Пошук у одному інтервалі останнього входжен-

find_first_of

ня іншого

 

 

 

Пошук у першому інтервалі одного зі значень

find_if

другого інтервалу

 

 

Пошук у інтервалі елемента, що задовольняє

for_each

предикат

 

 

 

Застосовує задану функцію (функтор) до всіх

 

елементів інтервалу

 

 

521

ПРОГРАМУВАННЯ

 

Продовження табл. 4.1.

Функція

Призначення

generate

Заповнює інтервал значеннями, що обчислені

generate_n

заданою функцією (функтором)

Заповнює перші n елементів контейнера зна-

 

ченнями, що обчислені заданою функцією (фу-

includes

нктором)

Перевіряє, чи входить один упорядкований

inplace_merge

інтервал у інший

Злиття на місці

iter_swap

Обмінює значення елементів, що адресовані

 

парою ітераторів, але не модифікує самі літе-

lexicographical_compare

ратори

Лексикографічно попарно порівнює два інтер-

lower_bound

вали

Бінарний пошук у впорядкованому інтервалі

 

першого елемента, більшого чи рівного задано-

make_heap

му

Конвертує елементи з діапазону в купу, в якій

 

перший елемент є найбільшим і для якої кри-

 

терій сортування може бути визначений бінар-

max

ним предикатом

Порівняти два елементи. Порівнює два об'єкти

 

й повертає більший із двох, де критерій може

max_element

бути визначений бінарним предикатом

Знаходить перше входження найбільшого еле-

 

мента в зазначеному діапазоні, де критерій

 

пошуку може бути визначений бінарним пре-

merge

дикатом

Запис об'єднаної послідовності в нову

min

Порівняти два елементи. Порівнює два об'єкти

 

й повертає менший із двох, де критерій може

min_element

бути визначений бінарним предикатом

Знаходить перше входження найменшого еле-

 

мента в зазначеному діапазоні, де критерій

 

пошуку може бути визначений бінарним пре-

mismatch

дикатом

Пошук перших незбіжних елементів у двох по-

next_permutation

слідовностях

Отримати наступну перестановку

nth_element

Елементи, менші за n-й, переміщуються ліво-

partial_sort

руч від нього, а більші – праворуч

Сортування початкової частини інтервалу

partial_sort_copy

Сортування початкової частини інтервалу з

 

копіюванням результату в новий контейнер

522

 

Розділ IV. АЛГОРИТМИ

 

Продовження табл. 4.1.

Функція

Призначення

partition

Переставлення елементів, що задовольняють

pop_heap

заданий предикат, на початок інтервалу

Видаляє найбільший елемент від початку купи

 

до останнього положення в діапазоні й потім

prev_permutation

формує нову купу з елементів, що залишилися

Отримати попередню перестановку

push_heap

Додає елемент із кінця діапазону до існуючої

 

купи, що складається з елементів, які передують

random_shuffle

діапазону

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

remove

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

remove_copy

нюють заданому

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

 

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

remove_copy_if

контейнер

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

 

льняють заданий предикат, результат скопію-

remove_if

вати в новий контейнер

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

replace

льняють заданий предикат

Замінити всі елементи інтервалу, що дорівню-

replace_copy

ють заданому, на нові

Замінити всі елементи інтервалу, що дорівню-

 

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

replace_copy_if

новий контейнер

Замінити всі елементи інтервалу, що задоволь-

 

няють заданий предикат, на нові, результат

replace_if

скопіювати в новий контейнер

Замінити всі елементи інтервалу, що задоволь-

reverse

няють заданий предикат, на нові

Переставити елементи інтервалу в оберненому

reverse_copy

порядку

Переставити елементи інтервалу в оберненому

 

порядку, результат скопіювати в новий кон-

rotate

тейнер

Циклічна перестановка елементів інтервалу

rotate_copy

Циклічна перестановка елементів інтервалу,

search

результат скопіювати в новий контейнер

Пошук в одному інтервалі першого входження

search_n

іншого

Пошук інтервалу з n елементів, що дорівнюють

set_difference

заданому

Різниця множин-інтервалів

523

ПРОГРАМУВАННЯ

 

 

Закінчення табл. 4.1.

Функція

 

Призначення

set_intersection

 

Перетин множин-інтервалів

 

set_symmetric_difference

Симетрична різниця множин-інтервалів

set_union

 

Об'єднання множин-інтервалів

sort

 

Сортування інтервалу

sort_heap

 

Конвертує купу до діапазону, що сортується

stable_partition

 

Перестановка елементів, що задовольняють

 

 

заданий предикат, на початок інтервалу зі збе-

stable_sort

 

реженням відносного порядку елементів

 

Перестановка елементів, що задовольняють

swap

 

заданий предикат, на початок інтервалу

 

Обмінює значення об'єктів

swap_ranges

 

Обмінює значення із двох інтервалів

transform

 

Застосовує задану функцію (функтор) до зада-

 

 

ного інтервалу (інтервалів) з отриманням нової

unique

 

послідовності елементів

 

Видаляє з інтервалу однакові сусідні елементи,

unique_copy

 

залишаючи єдиний

 

Видаляє з інтервалу однакові сусідні елементи,

 

 

залишаючи єдиний; результат скопіювати в

upper_bound

 

новий контейнер

 

Бінарний пошук у впорядкованому інтервалі

 

 

першого елемента, більшого за заданий

Таблиця 4.2. Алгоритми, визначені в заголовному файлі <numeric>

Функція

 

Призначення

accumulate

Обчислює суму значень елементів послідовності з

 

діапазону [first, last) з початковим значен-

 

ням. Наприклад, якщо задана послідовність

 

{1,2,2,4,5} і початкове значення 0, то результатом

 

роботи алгоритму буде 14. Операція додавання

 

може бути замінена іншою бінарною операцією,

adjacent_difference

що передається як параметр

Обчислює часткову різницю. Створює нову послі-

 

довність, в якій значення кожного елемента (крім

 

першого, що рівний першому елементу вихідного

 

інтервалу) дорівнює різниці поточного елемента та

 

його попередника у вихідній послідовності із за-

 

даного діапазону. Наприклад, якщо маємо {1, 3, 4,

 

5, 5, 7}, то результатом буде {1, 2, 1, 1, 0, 2}. За-

 

мість різниці у вихідну послідовність може бути

 

записаний результат деякої іншої узагальненої

 

процедури, яка є бінарною операцією

524

 

Розділ IV. АЛГОРИТМИ

 

 

 

Функція

ПризначенняЗакінчення табл. 4.2.

inner_product

Знаходить скалярний добуток двох послідовно-

 

 

 

стей з інтервалів. Наприклад, якщо послідовності

 

 

{1, 2, 4} та {1, 1, 2}, то результатом буде

 

 

1*1+2*1+4*2=11. Замість операцій додавання та

 

 

множення як параметри можна передати інші

 

partial_sum

бінарні операції

 

Обчислює часткову суму. Створює нову послідов-

 

 

ність із послідовності, обмеженої діапазоном

 

 

[first, last]: у новій послідовності значення

 

 

кожного елемента дорівнює сумі всіх попередніх,

 

 

включаючи й поточний. Наприклад, з послідовно-

 

 

сті {0, 1, 2, 2} буде створена послідовність {0, 1, 3,

 

 

5}. Замість операції суми можна використовувати

 

 

іншу бінарну операцію

 

*Література для CР:. динамічні структури даних і алгоритми на них – [8, 60, 65, 77, 95, 124, 125].

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

1.Що таке динамічні структури даних?

2.Що таке зв'язаний список?

3.Як реалізується однозв'язний список?

4.Які основні операції над однозв'язними списками?

5.Як реалізується двозв'язний список?

6.Як реалізуються стеки й операції на них?

7.Як реалізуються черги й операції на них?

8.Яка відмінність між стеком і чергою?

9.Яка відмінність зв'язаного списку від стеку й черги? 10. Як реалізується бінарне дерево?

11. Скільки всього є варіантів обходу бінарного дерева?

12. Що таке контейнер та ітератор?

13. Що таке послідовний контейнерний тип векторів?

14. Що таке послідовний контейнерний тип списків?

15. Що таке послідовний контейнерний тип двосторонніх черг? 16. Що таке асоційовані контейнерні типи відношень і множин? 17. Що таке стандартні узагальнені алгоритми?

18. Написати клас, що реалізує булеву алгебру множин цілих чи- сел з операціями та предикатами: введення-виведення, об'- єднання, перетин, різниця, симетрична різниця, включення, рівність, приналежність елемента множині. Множини подати

увигляді лінійного списку елементів.

525

ПРОГРАМУВАННЯ

19.Написати функції, що реалізують алгебру багаточленів від однієї змінної із цілими коефіцієнтами. Операції алгебри: введення-виведення, додавання, множення на одночлен і ба- гаточлен, ділення двох багаточленів (з остачею й часткою у вигляді багаточленів). Багаточлени подати як лінійний спи- сок пар (коефіцієнт, степінь змінної).

20.Циклічним називається список, останній елемент якого міс- тить не NULL, а показує на його голову. Реалізувати основні

операції для роботи з такими списками.

21. Написати програму для розв'язання відомої задачі: n солда- тів стали в коло. Із k -го солдата починається рахування. Че- рез p солдатів той, на кого випало, виходить із кола, а раху-

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

22.Написати програму для перетворення арифметичного вира- зу на форму ОПЗ, застосовуючи стек у вигляді масиву.

23.Реалізувати обчислення арифметичного виразу у формі ОПЗ.

24.Написати програму tail, що друкує n останніх введених ря- дків. За умовчанням n = 5 , але n може бути задано й у ко- мандному рядку. Командний рядок > tail - n викликає друкування останніх n рядків. У кожний момент зберігати в пам'яті не більше n рядків. Застосувати: а) чергу; б) цикліч- ний список у вигляді масивів.

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

а) заміну k -го вузла в черзі;

б) вилучення k -го вузла із черги; в) конкатенацію кількох черг; г) розбиття черги на кілька черг; д) створення копії черги; е) визначення довжини черги;

є) пошук вузла(ів) черги із заданими властивостями.

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

а) каталог книг у бібліотеці; б) список студентів у групі; в) список товарів у магазині ; г) список клієнтів банку; д) телефонний довідник.

27.Для таблиць із попереднього завдання написати програму на основі двозв'язного списку, що дозволяє додавати й видаля-

526

Розділ IV. АЛГОРИТМИ

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

28.Для таблиць із вправи 26 написати програму на основі біна- рного дерева пошуку (порядок лексикографічний за ключо- вим полем), що дозволяє додавати й видаляти дані списку, шукати інформацію за ключем, зберігати список у файл і зчитувати його з файла.

29.Для лінійного однозв'язного списку цілих чисел від кожного додатного числа відняти найменше з додатних. Процедуру продовжувати, поки всі елементи списку не стануть від'єм- ними. Зазначити кількість ітерацій у процедурі.

30.Написати функцію, що читає з клавіатури дужковий вираз і перевіряє його на приналежність мові Діка: а) для дужок ( , ); б) для дужок (,),[,],{,}. Використати стек у динамічній пам'яті.

31.Написати функції для роботи із загальними списками з ато- мами-ідентифікаторами: 1) створення й виведення списку;

2)пошуку всіх атомів списку; 3) пошуку частоти входжень усіх атомів у список; 4) усунення й заміни одного атома на інший.

32.Для завдань 18-30 використати відповідні контейнерні типи. Проаналізувати, який із варіантів програми простіший для реалізації й розуміння.

4.4.Динамічні таблиці

¾Таблиці як масиви структур

¾Таблиці у вигляді зв'язаних списків

¾Підвищення ефективності при пошуку в таблицях

¾Пряма адресація

¾Хеш-таблиці з колізіями

¾Відкрите хешування

¾Закрите хешування

¾Таблиці у вигляді дерев пошуку

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

527

ПРОГРАМУВАННЯ

У підрозд. 4.1 розглядалася задача пошуку елементів у таблицях фік- сованої довжини. Ми вже знаємо, що таблиця – це кортеж векторів пев- ної фіксованої структури. Самі вектори називаються рядками таблиці й подаються зазвичай структурами. Наприклад, якщо таблиця має вигляд

Прізвище, ім'я, по-батькові

Курс

Середній бал

Іваненко Іван Іванович

2

4.25

Петренко Петро Петрович

1

3.5

Сидоров Сидір Сидорович

1

5

то її рядок можна описати таким чином:

typedef struct student { char *key;

int rate;

float estimationsult; }Student;

Основні операції з таблицями: додавання й видалення рядка, мо- дифікація рядка, пошук рядка за ключем.

Реалізація операцій над таблицями залежить від способу подання таблиць. Розглянемо ці способи.

4.4.1. ТАБЛИЦІ ЯК МАСИВИ СТРУКТУР

Найпростішим є подання таблиць у вигляді динамічних масивів їх- ніх рядків:

Student tableStArray[n];

Приклад 4.26. Таблиця як масив структур:

Лістинг.

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h>

#int countLine=50;/*задає максимальну кількість рядків у таблиці*/

typedef struct student { char name[10];

int rate;

float estimationsult; }Student;

528

Розділ IV. АЛГОРИТМИ

typedef Student *StudentPtr;

Student tableStArray[countLine];

Student emptyCellArray;

/*ініціалізація інформації про студента*/ Student setEmtySt(Student st)

{

st.estimationsult=0; strcpy(st.name," "); st.rate=0;

return st;

}

/*друкування таблиці*/ void printArrayTable(void)

{

for(int i=0; i<countLine; i++) printf("\n%s\t%f\t%d", tableStArray[i].name,

tableStArray[i].estimationsult, tableStArray[i].rate);

}

/*ініціалізація таблиці*/ void ArrayTableInit(void)

{

emptyCellArray=setEmtySt(emptyCellArray); for(int i=0; i<countLine; i++)

tableStArray[i]=emptyCellArray;

}

/*пошук рядка в таблиці за ключовим полем name; результат – індекс рядка, якщо його знайдено, або countLine, якщо відповідного рядка немає*/

int ArrayTableFind(char key[10])

{

int i=0;

while((i<countLine)&&(strcmp(tableStArray[i].name, key))!=0) i++;

return i;

}

/*перевірка на рівність двох рядків*/ int StructEqual(Student st1, Student st2)

{

if((st1.rate==st2.rate)&&(st1.estimationsult==st2.estimation sult)&&(strcmp(st1.name, st2.name)))

return 1;

529

ПРОГРАМУВАННЯ

else return 0;

}

/*додавання рядка на першу вільну позицію в таблиці*/ void ArrayTableInsert(Student st)

{

int pos=ArrayTableFind(emptyCellArray.name); if(pos==countLine)

printf("\nТаблиця переповнена. Запис не відбув-

ся!!!\n");

else tableStArray[pos]=st;

}

/*видалення рядка за ключем*/

void ArrayTableDelete(char key[10])

{

int pos=ArrayTableFind(key); if(pos==countLine)

printf("Елемент для видалення не знайдено!"); else tableStArray[pos]=emptyCellArray;

}

■

4.4.2. ТАБЛИЦІ У ВИГЛЯДІ ЗВ'ЯЗАНИХ СПИСКІВ

Гнучкішим із погляду модифікації таблиць є їхнє подання у вигляді зв'язаних списків (див. підрозд. 4.3.1). Розглянемо реалізацію основ- них табличних операцій на основі однозв'язного списку.

Приклад 4.27. Таблиця як зв'язаний лінійний список:

#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <conio.h>

typedef struct item { char name[10];

int rate;

float estimationsult;

struct item *next; /*покажчик на наступний елемент списку*/ } Item;

typedef Item *Itemptr;

/*друкування значень елементів списку, start – голова списку*/ void display(Itemptr start)

530