Алгоритми роботи з даними, що представлені за принципом “купи” (heap). Приклади
Зміст
- 1. Алгоритм make_heap. Підготовити послідовність для використання в якості “купи”
- 2. Алгоритм push_heap. Додати останній елемент в існуючу “купу”
- 3. Алгоритм pop_heap. Видалити найбільший елемент з початку купи до позиції, що слідує за останньою, в діапазоні, а потім формує нову купу з елементів, що залишились
- 4. Алгоритм sort_heap. Посортувати числа в “купі”
- Споріднені теми
Пошук на інших ресурсах:
1. Загальні відомості про клас vector. Огляд методів класу
Клас vector представляє собою динамічний масив, розмір якого у програмі може змінюватись при необхідності. Цей клас є одним з найбільш універсальних та поширених у використанні при написанні програм на C++. Доступ до елементів класу здійснюється як до звичайного масиву з допомогою квадратних дужок [ ].
1. Алгоритм make_heap. Підготовити послідовність для використання в якості “купи”
Алгоритм make_heap має дві перевантажені реалізації, які оголошено наступним чином
template <class RandomAccessIterator> void make_heap( RandomAccessIterator first, RandomAccessIterator last ); template <class RandomAccessIterator, class BinaryPredicate> void make_heap( RandomAccessIterator first, RandomAccessIterator last, BinaryPredicate pred );
тут
- first – ітератор довільного доступу. Цей ітератор вказує на перший елемент діапазону, який потрібно конвертувати в “купу”;
- last – ітератор довільного доступу. Цей ітератор вказує на позицію яка слідує за останнім елементом діапазону, який конвертується в “купу”;
- pred – бінарний предикат, що задає умову при який один елемент менше за другий. Якщо умова виконується, то предикат повертає true, в противному випадку повертається false.
Приклад.
#include <iostream> #include <queue> #include <vector> #include <list> #include <functional> #include <algorithm> using namespace std; int main() { // Алгоритм make_heap - Створити купу на основі заданої послідовності. // У купі перший елемент є найбільшим (найменшим) а також критерій сортування // може бути визначений бінарним предикатом. // 1. Використання алгоритму без предикату // 1.1. Оголосити вектор та вивести його vector<int> V1 = { 2, 1, 3, 2, 4, 5, 2, 1, 3, 0 }; vector<int>::iterator it = V1.begin(); cout << "V1 => "; while (it != V1.end()) { cout << *it << " "; it++; } cout << endl; // 1.2. Створити "купу" (heap) з послідовності make_heap(V1.begin(), V1.end()); // 1.3. Вивести знову V1 cout << "V1 => "; for (int i : V1) cout << i << " "; cout << endl; // 2. Використання алгоритму зі стандартним предикатом // 2.1. Оголосити ще один вектор та вивести його vector<int> V2 = { 2, 1, 3, 2, 4, 5, 2, 1, 3, 0 }; it = V2.begin(); cout << "V2 => "; while (it != V2.end()) { cout << *it << " "; it++; } cout << endl; // 2.2. Створити купу на основі стандартного предикату less make_heap(V2.begin(), V2.end(), less<int>()); // 2.3. Вивести вектор it = V2.begin(); cout << "V2 => "; while (it != V2.end()) { cout << *it << " "; it++; } cout << endl; }
Результат
V1 => 2 1 3 2 4 5 2 1 3 0 V1 => 5 4 3 3 1 2 2 1 2 0 V2 => 2 1 3 2 4 5 2 1 3 0 V2 => 5 4 3 3 1 2 2 1 2 0
⇑
2. Алгоритм push_heap. Додати останній елемент в існуючу “купу”
Алгоритм має дві реалізації
template <class RandomAccessIterator> void push_heap( RandomAccessIterator first, RandomAccessIterator last ); template <class RandomAccessIterator, class BinaryPredicate> void push_heap( RandomAccessIterator first, RandomAccessIterator last, BinaryPredicate pred);
тут
- first, last – ітератори довільного доступу, які вказують відповідно на перший та останній елементи діапазону, який розглядається як потенційна “купа”;
- pred – бінарний предикат, який повертає true, якщо перший елемент менший за інший.
Приклад.
#include <iostream> #include <queue> #include <vector> #include <list> #include <functional> #include <algorithm> using namespace std; void PrintVector(vector<int>& V, string msg) { cout << msg << " => "; for (int i : V) cout << i << " "; cout << endl; } int main() { // Алгоритм push_heap - Додати елемент в існуючу купу, купа змінюється. // У купі перший елемент є найбільшим (найменшим) а також критерій сортування // може бути визначений бінарним предикатом. // 1. Використання алгоритму без предикату // 1.1. Оголосити вектор та вивести його vector<int> V1 = { 2, 1, 3, 4 }; PrintVector(V1, "V1"); // 1.2. Створити "купу" (heap) з послідовності make_heap(V1.begin(), V1.end()); PrintVector(V1, "make_heap(V1)"); // 1.3. Додати елемент до послідовності та вивести послідовність знову V1.push_back(23); PrintVector(V1, "V1+1"); // 1.4. Додати елемент в існуючу купу push_heap(V1.begin(), V1.end()); PrintVector(V1, "V1.push_heap"); // 2. Використання алгоритму зі стандартним предикатом greater // 2.1. Створити вектор vector<int> V2 = { 5, 9, 7, 3 }; PrintVector(V2, "V2"); // 2.2. Створити купу make_heap(V2.begin(), V2.end()); PrintVector(V2, "make_heap(V2)"); // 2.3. Додати елемент до послідовності V2 V2.push_back(4); PrintVector(V2, "V2+1"); // 2.4. Додати елемент в існуючу купу - предикат greater push_heap(V2.begin(), V2.end(), greater<int>()); PrintVector(V2, "push_heap(V2)"); }
Результат
V1 => 2 1 3 4 make_heap(V1) => 4 2 3 1 V1+1 => 4 2 3 1 23 V1.push_heap => 23 4 3 1 2 V2 => 5 9 7 3 make_heap(V2) => 9 5 7 3 V2+1 => 9 5 7 3 4 push_heap(V2) => 4 9 7 3 5
⇑
3. Алгоритм pop_heap. Видалити найбільший елемент з початку купи до позиції, що слідує за останньою, в діапазоні, а потім формує нову купу з елементів, що залишились
Алгоритм pop_heap має два перевантажені варіанти реалізації, що відрізняються відсутністю/наявністю предикату:
template <class RandomAccessIterator> void pop_heap( RandomAccessIterator first, RandomAccessIterator last); template <class RandomAccessIterator, class BinaryPredicate> void pop_heap( RandomAccessIterator first, RandomAccessIterator last, BinaryPredicate pred);
тут
- first, last – ітератори довільного доступу, які вказують відповідно на перший та останній елементи діапазону, який розглядається як потенційна “купа”;
- pred – бінарний предикат, який повертає true, якщо перший елемент менший за інший.
Приклад.
#include <iostream> #include <queue> #include <vector> #include <list> #include <functional> #include <algorithm> using namespace std; void PrintVector(vector<int>& V, string msg) { cout << msg << " => "; for (int i : V) cout << i << " "; cout << endl; } int main() { // Алгоритм pop_heap - видалити найбільший елемент з купи з її подальшим переформуванням. // У купі перший елемент є найбільшим (найменшим) а також критерій сортування // може бути визначений бінарним предикатом. // 1. Використання алгоритму без предикату // 1.1. Оголосити вектор та вивести його vector<int> V1 = { 2, 1, 3, 4 }; PrintVector(V1, "V1"); // 1.2. Створити "купу" (heap) з послідовності make_heap(V1.begin(), V1.end()); PrintVector(V1, "make_heap(V1)"); // 1.3. Додати елемент до послідовності та вивести послідовність знову V1.push_back(23); PrintVector(V1, "V1+1"); // 1.4. Додати елемент в існуючу купу push_heap(V1.begin(), V1.end()); PrintVector(V1, "V1.push_heap"); // 1.5. Витягти найбільший елемент з існуючої купи - алгоритм pop_heap pop_heap(V1.begin(), V1.end()); V1.resize(V1.size() - 1); PrintVector(V1, "V1.pop_heap"); // 2. Використання алгоритму зі стандартним предикатом greater // 2.1. Створити вектор vector<int> V2 = { 5, 9, 7, 3 } PrintVector(V2, "V2"); // 2.2. Створити купу make_heap(V2.begin(), V2.end()); PrintVector(V2, "make_heap(V2)"); // 2.3. Додати елемент до послідовності V2 V2.push_back(4); PrintVector(V2, "V2+1"); // 2.4. Додати елемент в існуючу купу - предикат greater push_heap(V2.begin(), V2.end(), greater<int>()); PrintVector(V2, "push_heap(V2)"); // 2.5. Витягти найбільший елемент з існуючої купи pop_heap(V2.begin(), V2.end(), greater<int>()); V2.resize(V2.size() - 1); PrintVector(V2, "V2.pop_heap"); }
Результат
V1 => 2 1 3 4 make_heap(V1) => 4 2 3 1 V1+1 => 4 2 3 1 23 V1.push_heap => 23 4 3 1 2 V1.pop_heap => 4 2 3 1 V2 => 5 9 7 3 make_heap(V2) => 9 5 7 3 V2+1 => 9 5 7 3 4 push_heap(V2) => 4 9 7 3 5 V2.pop_heap => 5 9 7 3
⇑
4. Алгоритм sort_heap. Посортувати числа в “купі”
Алгоритм має дві перевантажені реалізації
template <class RandomAccessIterator> void sort_heap( RandomAccessIterator first, RandomAccessIterator last); template <class RandomAccessIterator, class Compare> void sort_heap( RandomAccessIterator first, RandomAccessIterator last, Compare pred);
тут
- first, last – ітератори довільного доступу, які вказують відповідно на перший та останній елементи діапазону, який розглядається як потенційна “купа”;
- pred – бінарний предикат, який повертає true, якщо перший елемент менший за інший.
Приклад.
#include <iostream> #include <algorithm> #include <vector> #include <functional> #include <ostream> using namespace std; void print(const string& s, const vector<int>& v) { cout << s << " => "; for (auto i = v.begin(); i != v.end(); i++) { cout << *i << " "; } cout << endl; } int main() { // Алгоритм sort_heap - посортувати числа в "купі" (heap) // 1. Створити вектор і вивести його vector<int> V1 = { 2, -1, 3, 8, 4, 0, 5, 3, 1 }; print("V1", V1); // 2. Конвертувати послідовність V1 в "купу" make_heap(V1.begin(), V1.end()); // 3. Посортувати числа в "купі" sort_heap(V1.begin(), V1.end()); // 4. Вивести результат print("sort_heap(V1)", V1); }
Результат
V1 => 2 -1 3 8 4 0 5 3 1 sort_heap(V1) => -1 0 1 2 3 3 4 5 8
⇑
Споріднені теми
- Алгоритми визначення мінімуму і максимуму. Алгоритми min, min_element, max, max_element, lexicographical_compare
- Алгоритми перестановок. Алгоритми next_permutation, prev_permutation
- Немодифікуючі алгоритми. Пошук. Алгоритми find, find_if, find_first_of, find_end, adjanced_find, search, search_n
- Немодифікуючі алгоритми. Алгоритми count, count_if, equal, equal_range, mismatch
- Алгоритми для роботи з множинами. Алгоритми includes, set_union, set_intersection, set_difference, set_symmetric_difference
⇑