Les_27_adaptery.ppt
- Количество слайдов: 19
Контейнерні адаптери
• Адаптери базових контейнерів: – стек stack, – черга queue, – черга з пріоритетами priority_queue. • Побудовані на основі базових послідовностей (vector, list, deque). • Для кожного адаптора встановлено контейнер за замовчуванням, що найкраще підходить для його представлення (ефективно реалізує його методи) • Адаптери представляють обмежений інтерфейс до контейнера: - не надають ітераторів; - використовуються тільки через їх спеціалізовані інтерфейси
Стек stack • Шаблонний адаптерний контейнер, підтримує структуру даних LIFO • Основні методи: push() – додає новий елемент у вершину стеку top() – повертає значення елемента з вершини стеку pop() – видаляє елемент з вершини стеку (не повертає елемент) top() push() pop()
Стек stack • Шаблонний адаптерний контейнер, підтримує структуру даних LIFO • Основні методи: push() – додає новий елемент у вершину стеку top() – повертає значення елемента з вершини стеку pop() – видаляє елемент з вершини стеку (не повертає елемент) top()
• Визначений в заголовковому файлі <stack> template<class _Ty, class _Container = deque<_Ty>> class stack{ protected: _Container c; public: typedef _Container container_type; typedef typename _Container: : value_type; typedef typename _Container: : size_type; stack(): c(){} конструктори explicit stack (const _Container& _Cont): c(_Cont){ } bool empty() const {return (c. empty()); } size_type size() const{ return (c. size()); } сonst value_type& top() { return (c. back()); } void push(const value_type& _Val) { c. push_back(_Val); } void pop(){c. pop_back(); } };
• За замовчуванням стек використовує контейнер deque для зберігання своїх елементів: stack<string> stack 1; // використовує deque<string> //для зберігання елементів типу string • явно вказати інший тип контейнера: stack<int, vector<int> > stack 2; // використовує vector<int> //для зберігання елементів типу int stack<char, list<char> > stack 3; // використовує list<char> //для зберігання елементів типу char • Елементи, які додаються в стек, копіюються в контейнер, що його реалізує. • До двох стеків одного типу можна застосовувати операції порівняння (==, !=, <, >, <=, >=) якщо вони визначені над елементами стеку.
Функція stack. Out() очікує інтерфейс stack, решта частина програми вимагає об’єкти, записані в list. // Expects a stack: template<class Stk> void stack. Out(Stk& s, ostream& os = cout) { while(!s. empty()) { os << s. top() << "n"; s. pop(); } } int main() { ifstream in("f. cpp"); list<Line> lines; // Read file and store lines in the list: string s; while(getline(in, s)) lines. push_front(s); // Turn the list into a stack for printing: stack<Line, list<Line> > stk(lines); stack. Out(stk); } ///: ~ class Line { string line; size_t lspaces; public: Line(string s) : line(s) { lspaces = line. find_first_not_of(' '); if(lspaces == string: : npos) lspaces = 0; line = line. substr(lspaces); } friend ostream& operator<<(ostream& const Line& l) { for(size_t i = 0; i < l. lspaces; i++) os << ' '; return os << l. line; } // Other functions here. . . };
Черга (queue) • шаблонний адаптерний контейнер • queue - реалізує метод доступу FIFO. (елементи вставляються в кінець черги, а отримуються з початку черги) • Основні методи: pop() – видаляє елемент з черги (не повертає елемента) front() – повертає значення першого елемента черги back() – повертає значення останнього елемента черги push(item) – додає новий елемент в кінець черги.
• Визначена в заголовковому файлі <queue> template<class _T, class _Container = deque<_T>> class queue{ protected: _Container c; public: … queue(): c(){} explicit queue (const _Container& _Cont): c(_Cont){ } bool empty() const {return (c. empty()); } size_type size() const{ return (c. size()); } value_type& front() { return (c. front()); } const value_type& front()const { return (c. front()); } value_type& back() { return (c. back()); } const value_type& back()const { return (c. back()); } void push(const value_type& _Val) { c. push_back(_Val); } void pop(){c. pop_front(); } };
• За замовчуванням черга використовує контейнер deque для зберігання своїх елементів: queue<string> qu 1; // використовує deque<string> //для зберігання елементів типу string • Можна використовувати і інші контейнери, які надають операції front(), back(), push_back(), pop_front(): queue<char, list<char> > qu 3; // використовує list<char> //для зберігання елементів типу char • vector не має методу pop_front(): queue <int, vector<int> > q 3; q 3. push( 10 ); q 3. pop( ); • Елементи, які додаються в чергу, копіюються в контейнер, що його реалізує. • До двох черг одного типу можна застосовувати операції порівняння (==, !=, <, >, <=, >=) якщо вони визначені над елементами черги. queue<int> q 1; q 1. push(2); q 1. push(4); queue<int> q 2(q 1); q 2. push(3); q 1. push(4); cout<< “q 1<q 2 ? ”<< q 1<q 2<<“ q 1==q 2 ? ”<< q 1==q 2;
• Доступ до контейнера, що зберігає елементи адаптера, можливий лише у похідних класах class Customer. Q : public queue<Customer> { public: friend ostream& operator<<(ostream& os, const Customer. Q& cd) { copy(cd. c. begin(), cd. c. end(), ostream_iterator<Customer>(os, "")); return os; } }; Customer. Q customers; for(int i = 0; i < rand() % 5; i++) customers. push(Customer(rand() % 15 + 1)); cout << customers << endl;
Черга з пріоритетами (priority_queue) • • шаблонний адаптерний контейнер priority_queue – елементи співставляються з їх пріоритетами (елемент вставляється у відсортовану чергу згідно з функцією порівняння або функціональним об’єктом) • • Необхідно задавати спосіб визначення пріоритетів Основні методи: pop() - видаляє елемент з найвищим пріоритетом top() – повертає значення елемента з найвищим пріоритетом (не видаляє його). push(item) - додає новий елемент в позицію, згідно з його пріоритетом.
• Визначена в заголовковому файлі <queue> template<class _T, class C = vector<_T>, class Cmp=less<typename C: : value_type>> class priority_ queue{ protected: C c; Cmp cmp; public: explicit priority_ queue (const Cmp& a 1=Cmp(), const C& a 2=C())): c(a 2), cmp(a 1){ } bool empty() const {return (c. empty()); } size_type size() const{ return (c. size()); } const value_type& top()const { return (c. front()); } void push(const value_type& ); void pop(); };
• За замовчуванням черга з пріоритетами будується на основі контейнера vector. • Можна використовувати і інші контейнери, які надають операції front(), push_back(), pop_back() та ітератор довільного доступу priority_queue<int> pqi; srand(time(0)); // Seed the random number generator cout<<"random numbers: "<<endl; for(int i = 0; i < 100; i++) { int temp=rand() % 25; pqi. push(temp); cout<<temp<<' '; } cout<<endl<<"priority_queue: "<<endl; while(!pqi. empty()) { cout << pqi. top() << ' '; pqi. pop(); }
• Змінюємо пріоритет елементів, через задання функціонального об’єкта priority_queue<int, vector<int>, greater<int> > pqi; srand(time(0)); // Seed the random number generator cout<<"random numbers: "<<endl; for(int i = 0; i < 100; i++) { int temp=rand() % 25; pqi. push(temp); cout<<temp<<' '; } cout<<endl<<"priority_queue: "<<endl; while(!pqi. empty()) { cout << pqi. top() << ' '; pqi. pop(); }
• Змінюємо пріоритет елементів, через задання власної функції порівняння class To. Do. Item { char primary; int secondary; string item; public: To. Do. Item(string td, char pri = 'A', int sec = 1) : primary(pri), secondary(sec), item(td) {} friend bool operator<(const To. Do. Item& x, const To. Do. Item& y) { if(x. primary > y. primary) return true; if(x. primary == y. primary) if(x. secondary > y. secondary) return true; return false; } friend ostream& operator<<(ostream& os, const To. Do. Item& td) { return os << td. primary << td. secondary << ": " << td. item; } }; int main() { priority_queue<To. Do. Item> pq; pq. push(To. Do. Item("Empty trash", 'C', 4)); pq. push(To. Do. Item("Feed dog", 'A', 2)); pq. push(To. Do. Item("Feed bird", 'B', 7)); pq. push(To. Do. Item("Mow lawn", 'C', 3)); pq. push(To. Do. Item("Water lawn", 'A', 1)); pq. push(To. Do. Item("Feed cat", 'B', 1)); while(!pq. empty()) { cout << pq. top() << endl; pq. pop(); } } A 1: Water lawn A 2: Feed dog B 1: Feed cat B 7: Feed bird C 3: Mow lawn C 4: Empty trash
• доступ до контейнера, який зберігає елементи priority_queue здійснюється через захищене поле с у похідних класах int main() { PQI pqi; srand(time(0)); for(int i = 0; i < 100; i++) pqi. push(rand() % 25); cout<<"by iterator: "<<endl; copy(pqi. impl(). begin(), pqi. impl(). end(), ostream_iterator<int>(cout, " ")); cout<<endl<<"by top-pop: "<<endl; while(!pqi. empty()) { cout << pqi. top() << ' '; pqi. pop(); }} class PQI : public priority_queue<int> { public: vector<int>& impl() { return c; } };
• priority_queue насправді будується через методи make_heap( ), push_heap( ) і pop_heap( ), тобто у вигляді купи (дерева), записаної в vector template<class T> class PQV : public priority_queue<T> { public: typedef vector<T> TVec; TVec get. Vector() { TVec r(this->c. begin(), this->c. end()); // c is already a heap sort_heap(r. begin(), r. end(), this->comp); // Put it into priority-queue order: reverse(r. begin(), r. end()); return r; } int main() { }; PQV<int> pqv; srand(time(0)); for(int i = 0; i < 100; i++) pqv. push(rand() % 25); const vector<int>& v = pqv. get. Vector(); copy(v. begin(), v. end(), ostream_iterator<int>(cout, " ")); cout << "n------" << endl; while(!pqv. empty()) { cout << pqv. top() << ' '; pqi. pop(); }
Les_27_adaptery.ppt