Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП_KAZYMYR.doc
Скачиваний:
14
Добавлен:
09.11.2019
Размер:
3.71 Mб
Скачать

5.3.3.Узагальнені алгоритми

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

Поведінка, що забезпечена стандартними класами STL, є мінімальною. Замість деталізації кожний клас може функціонувати разом з більшим набором узагальнених алгоритмів, наявних у бібліотеці. Ці алгоритми не залежать від контейнерів і можуть працювати з різними структурами, що, в остаточному підсумку, різко заощаджує обсяг бібліотеки. Більше того, функції, реалізовані, як узагальнені алгоритми, можуть застосовуватися зі звичайними покажчиками, масивами й іншими типами даних мови С++.

Нижче приводиться приклад побудови узагальненого алгоритму, що дозволяє знайти перше входження заданого елемента в контейнер:

template <class InputIterator, class T>

InputIterator find (InputIterator first, InputIterator last, const T& value) {while (first != last && first != value) {

++ first;

}

return first;

}

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

int data[100];

……………

int * value;

where = find (data, data+100, 7);

Пошук у списку буде нічим не складніше:

List <int> aList;

List <int> :: iterator where;

where = find (aList.begin(), aList.end(), 7);

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

template <class T>

void f(T a, int size) {...………} // припустимо

template <class T>

void g(int b) {...………} // не припустимо

Приклад 5.1.

Реалізація алгоритму Дейкстри пошуку найкоротшого шляху в графі доріг із вказівкою початкового міста. Як основу для побудови графа будемо розглядати карту (map), зображену на рис. 5.2.

Mic

Рис. 5.2. Карта доріг для прикладу 5.1

Дану карту будемо представляти у вигляді індексованого словника, що містить набір пара <ключ ><значення >:

typedef map <string, int> string Vector;

//вектор цілих-індексовані рядки

typedef map <string, stringVector> graph;

//двовимірний масив - індексовані рядки

string Ch(“Чернігів”);

string Kiyv(“Київ”);

string Sumy(“Суми”);

string Kh(“Харків”);

string Od(“Одеса”);

string Zap(“Запоріжжя”);

string Mic(“Миколаїв”);

graph cityMap; // двовимірний масив - відстані між містами

cityMap [Ch][Sumy] = 400;

cityMap [Ch][Kiev] = 150;

cityMap [Sumy][Kh] = 550;

cityMap [Kiev][Kh] = 500;

cityMap [Kh][Zap] = 400;

cityMap [Kh][Od] = 600;

cityMap [Zap][Nic] = 400;

cityMap [Od][Nic] = 150;

Для фіксування пар <відстань-місто> будемо використовувати пріоритетну чергу, вважаючи, що перший елемент місто, відстань до якого дорівнює 0, у підсумку пріоритетна черга буде містити міста в порядку від найближчого до самого далекого:

struct DinstancePair {

unsigned int first;

string second;

DinstancePair(): first(0){};

DinstancePair(int f, string & s): first(f), second(s) {};

};

bool operator < (DinstancePair & lhs, DinstancePair & rhs){

lhs.first < rhs.first;

}

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

void ShorttestDist (const graph & cityMap,

const string & start,

stringVector & dist) {

priority_quene <DinstancePair,

Vector <DinstancePair >,

greater <DinstancePair>

> que;

que.push(DinstancePair(0, start));

while (! Que.empty()){

int dinstance = que.top().first;

srting city = que.top().second;

que.pop();

if (0 = = dinstance.count(city))

{dist[city] = dinstance;

srtingVector::iterator start, stop;

start = cityMap[city].begin();

stop = cityMap[city].end();

for (; start != stop; ++start)

que.push(DinstancePair(dinstance + *(start).first,

*(start).second));

};

};

}

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

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

  1. Від яких класів будується ієрархія потокових класів в С++?

  1. Як можна задати форматоване введення/виведення?

  2. Для чого потрібні контейнерні класи?

  3. Який клас забезпечує функціонування контейнерних класів?

  4. За допомогою якої конструкції коду визначаються узагальнені алгоритми?

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