11 Iterated Containers

539 views

Published on

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
539
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
5
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

11 Iterated Containers

  1. 1. Бублик Володимир Васильович Програмування - 2 Лекція 1 1. Ієрархічне програмування. Ітератори в контейнерах Лекції для студентів 2 курсу
  2. 2. Повторення . Ітерований список <ul><li>class List </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>List(); </li></ul><ul><li>~List(); </li></ul><ul><li>void add( const Elem& elem); </li></ul><ul><li>const Elem& get() const ; </li></ul><ul><li>void begin() const { _current = _start;} </li></ul><ul><li>void next() const { _current = _current -> _next; } </li></ul><ul><li>bool done() const { return _current == 0; } </li></ul><ul><li>} ; </li></ul>
  3. 3. Питання <ul><li>Чи залежить ітератор від самого контейнера? ― Так, оскільки він є частиною класу </li></ul><ul><li>Висновок: </li></ul><ul><li>Невдале рішення: для користування ітератором ми повинні точно знати тип контейнера </li></ul>
  4. 4. Вивід списку <ul><li>ostream& operator <<(ostream & os, const List& l st ) </li></ul><ul><li>{ </li></ul><ul><li>l st . begin (); </li></ul><ul><li>while (!l st . done ()) </li></ul><ul><li>{ </li></ul><ul><li>os<<l st .get()<<':'; </li></ul><ul><li>l st .next(); </li></ul><ul><li>} </li></ul><ul><li>return os; </li></ul><ul><li>} </li></ul>
  5. 5. Узагальнений вивід <ul><li>template < class Container> </li></ul><ul><li>ostream& operator <<(ostream & os, const Container & c ) </li></ul><ul><li>{ </li></ul><ul><li>c . begin (); </li></ul><ul><li>while (! c . done ()) </li></ul><ul><li>{ </li></ul><ul><li>os<< c .get()<<':'; </li></ul><ul><li>c .next(); </li></ul><ul><li>} </li></ul><ul><li>return os; </li></ul><ul><li>} </li></ul>
  6. 6. Оцінка <ul><li>Узагальнені функції дають можливість генерувати потрібні засоби за єдиним шаблоном. Але це все ще невдале рішення з точки зору економії коду: кожен тип контейнера використовує власну конкретизацію шаблона </li></ul>
  7. 7. Аналіз вимог (1) <ul><li>Функція оперує лише інтерфейсом ітератора </li></ul><ul><li>ostream& operator <<(ostream & os, const Itor & it ) </li></ul><ul><li>{ </li></ul><ul><li>it . begin (); </li></ul><ul><li>while (! it . done ()) </li></ul><ul><li>{ </li></ul><ul><li>os<< it . get ()<<':'; </li></ul><ul><li>it . next (); </li></ul><ul><li>} </li></ul><ul><li>return os; </li></ul><ul><li>} </li></ul>
  8. 8. Аналіз вимог (2) <ul><li>Допускається як читання, так і запис елементів даних до контейнера </li></ul><ul><li>void process (Itor& it) </li></ul><ul><li>{ </li></ul><ul><li>for (it.begin(); !it.done(); it.next()) //C style </li></ul><ul><li>{ </li></ul><ul><li>it. put ( it. get () +1 ) ; </li></ul><ul><li>} </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul>
  9. 9. 1. Індивідуальні контейнери
  10. 10. Абстрактний ітератор <ul><li>Зберемо інтерфейс в абстрактний клас </li></ul><ul><li>class Itor </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>virtual ~Itor(){ }; </li></ul><ul><li>virtual void begin () const = 0; </li></ul><ul><li>virtual const Elem& get () const =0; </li></ul><ul><li>virtual void put ( const Elem &) = 0; </li></ul><ul><li>virtual bool done () const = 0; </li></ul><ul><li>virtual void next () const = 0; </li></ul><ul><li>}; </li></ul>
  11. 11. Неітерований список <ul><li>class List </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>List(); </li></ul><ul><li>~List(); </li></ul><ul><li>List& add( const Elem& elem); </li></ul><ul><li>void del(); </li></ul><ul><li>bool empty() const { return _amount==0;} </li></ul><ul><li>int amount() const { return _amount;} </li></ul><ul><li>private : </li></ul><ul><li>List ( const List&); </li></ul><ul><li>List& operator = ( const List&); </li></ul>
  12. 12. Неітерований список <ul><li>// Реалізація </li></ul><ul><li>protected : </li></ul><ul><li>struct Node </li></ul><ul><li>{ </li></ul><ul><li>Elem _elem; </li></ul><ul><li>Node * _next; </li></ul><ul><li>Node * _prev; </li></ul><ul><li>}; </li></ul><ul><li>Node * _start; </li></ul><ul><li>int _amount; </li></ul><ul><li>}; </li></ul>
  13. 13. Змішування інтерфейсів <ul><li>class IteratedList: public Itor, public List </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>mutable Node * _current; // на вузол списку </li></ul><ul><li>public : </li></ul><ul><li>IteratedList(); </li></ul><ul><li>virtual void begin () const ; </li></ul><ul><li>virtual const Elem& get() const ; </li></ul><ul><li>virtual bool done() const ; </li></ul><ul><li>virtual void next() const ; </li></ul><ul><li>virtual void put( const Elem &); </li></ul><ul><li>}; </li></ul>
  14. 14. Реалізація <ul><li>IteratedList :: IteratedList():_current(0) </li></ul><ul><li>{ </li></ul><ul><li>}; </li></ul><ul><li>const Elem& IteratedList :: get() const </li></ul><ul><li>{ </li></ul><ul><li>return _current->_elem; </li></ul><ul><li>} </li></ul><ul><li>void IteratedList :: put ( const Elem & elem) </li></ul><ul><li>{ </li></ul><ul><li>_current->_elem = elem; </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul>
  15. 15. Реалізація <ul><li>bool IteratedList :: done() const </li></ul><ul><li>{ </li></ul><ul><li>return _current == 0; </li></ul><ul><li>} </li></ul><ul><li>void IteratedList :: next() const </li></ul><ul><li>{ </li></ul><ul><li>_current= _current->_next; </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul>
  16. 16. Масив <ul><li>class Array </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>explicit Array (size_t); </li></ul><ul><li>~Array(); </li></ul><ul><li>Elem& operator [] (size_t index); </li></ul><ul><li>const Elem& operator [] (size_t index) const ; </li></ul><ul><li>size_t size() const ; </li></ul><ul><li>private : </li></ul><ul><li>size_t _size; </li></ul><ul><li>Elem * _pElem; </li></ul><ul><li>}; </li></ul>
  17. 17. Ітерований масив <ul><li>class IteratedArray: public Itor, public Array </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>mutable size_t _current; </li></ul><ul><li>public : </li></ul><ul><li>IteratedArray(size_t n): Array(n){}; </li></ul><ul><li>virtual void begin () const ; </li></ul><ul><li>virtual const Elem& get() const ; </li></ul><ul><li>virtual bool done() const ; </li></ul><ul><li>virtual void next() const ; </li></ul><ul><li>virtual void put( const Elem &); </li></ul><ul><li>}; </li></ul>
  18. 18. Реалізація <ul><li>const Elem& IteratedArray::get() const </li></ul><ul><li>{ </li></ul><ul><li>return (* this )[_current]; </li></ul><ul><li>} </li></ul><ul><li>bool IteratedArray::done() const </li></ul><ul><li>{ </li></ul><ul><li>return _current == size(); </li></ul><ul><li>} </li></ul><ul><li>void IteratedArray::put( const Elem & elem) </li></ul><ul><li>{ </li></ul><ul><li>(* this )[_current] = elem; return ; </li></ul><ul><li>} </li></ul>
  19. 19. Реалізація <ul><li>IteratedArray :: IteratedArray (size_t n): Array(n) </li></ul><ul><li>{ </li></ul><ul><li>}; </li></ul><ul><li>void IteratedArray::begin() const </li></ul><ul><li>{ </li></ul><ul><li>_current = 0; return ; </li></ul><ul><li>} </li></ul><ul><li>void IteratedArray::next() const </li></ul><ul><li>{ </li></ul><ul><li>++_current; return ; </li></ul><ul><li>} </li></ul>
  20. 20. Діаграма індивідуальних контейнерів
  21. 21. Сценарій спільного вживання <ul><li>// Створення ітерованого списку </li></ul><ul><li>IteratedList lst; </li></ul><ul><li>lst.add('a').add('b').add('c').add('d'); </li></ul><ul><li>// Створення ітерованого масиву </li></ul><ul><li>IteratedArray ar(5); </li></ul><ul><li>ar[0]='z'; ar[1]='y'; ar[2]='x'; ar[3]='w'; ar[4]='v'; </li></ul><ul><li>// Обробка спільною функцією process ( Itor &) </li></ul><ul><li>process (lst); </li></ul><ul><li>process (ar); </li></ul>
  22. 22. Недолік <ul><li>Кожен ітератор в силу успадкування містить в собі екземпляр контейнера. Виникає проблема використання кількох ітераторів в межах одного контейнера (особливо за умови закритого копіювання контейнерів) </li></ul>
  23. 23. Питання <ul><li>Чи потрібен ітераторам інтерфейс списку і, відповідно, інтерфейс масиву? </li></ul>
  24. 24. 2. Вбудовані індивідуальні ітератори
  25. 25. Підхід STL <ul><li>Спеціалізовані ітератори, вбудовані в конкретні класи контейнерів </li></ul>
  26. 26. Ітератор, вбудований до масиву <ul><li>class Array </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>explicit Array (size_t); </li></ul><ul><li>~Array(); </li></ul><ul><li>Elem& operator [] (size_t index); </li></ul><ul><li>const Elem& operator [] (size_t index) const ; </li></ul><ul><li>size_t size() const ; </li></ul><ul><li>class Iterator ; </li></ul><ul><li>}; </li></ul>
  27. 27. Агрегування масиву ітератором <ul><li>class Array:: Iterator: public Itor </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>Array * _toIterate; </li></ul><ul><li>mutable size_t _current; </li></ul><ul><li>public : </li></ul><ul><li>Iterator(Array& ar ): _toIterate(& ar ){}; </li></ul><ul><li> virtual void begin () const ; </li></ul><ul><li>virtual const Elem& get() const ; </li></ul><ul><li>virtual bool done() const ; </li></ul><ul><li>virtual void next() const ; </li></ul><ul><li>virtual void put( const Elem &); </li></ul>
  28. 28. Ітератор, вбудований до списку <ul><li>class List </li></ul><ul><li>{ </li></ul><ul><li>private : // Закриваємо реалізацію списку </li></ul><ul><li>struct Node </li></ul><ul><li>{ </li></ul><ul><li>Elem _elem; Node * _next; Node * _prev; </li></ul><ul><li>}; </li></ul><ul><li>Node * _start; </li></ul><ul><li>int _amount; </li></ul><ul><li>public : </li></ul><ul><li>class Iterator; </li></ul>
  29. 29. Агрегування списку ітератором <ul><li>clas s List:: Iterat or : public Itor </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>List & _toIterate ; </li></ul><ul><li>mutable Node * _current; </li></ul><ul><li>public : </li></ul><ul><li>Iterat or (List& lst): _toIterate(lst),_ current(0){}; </li></ul><ul><li>virtual void begin () const ; </li></ul><ul><li>virtual const Elem& get() const ; </li></ul><ul><li>virtual bool done() const ; </li></ul><ul><li>virtual void next() const ; </li></ul><ul><li>virtual void put( const Elem &); </li></ul>
  30. 30. Сценарій спільного вживання <ul><li>// Створення списку і встановлення ітератора </li></ul><ul><li>List lst; lst.add('a').add('b').add('c').add('d'); </li></ul><ul><li>List::Iterator ilst (lst); </li></ul><ul><li>// Створення масиву і встановлення ітератора </li></ul><ul><li>IteratedArray ar(5); </li></ul><ul><li>ar[0]='z'; ar[1]='y'; ar[2]='x'; ar[3]='w'; ar[4]='v'; </li></ul><ul><li>Array::Iterator iar (ar); </li></ul><ul><li>// Обробка спільною функцією process ( Itor &) </li></ul><ul><li>process (ilst); </li></ul><ul><li>process ( i ar); </li></ul>
  31. 31. 3. Копіювальні ітератори
  32. 32. Сортування масиву <ul><li>void sort(Array & ar) </li></ul><ul><li>{ </li></ul><ul><li>for (size_t i=0; i<ar.size(); ++i) </li></ul><ul><li>{ </li></ul><ul><li>size_t j=i ; </li></ul><ul><li>for (size_t k=i+1 ; k<ar.size(); ++k) </li></ul><ul><li>if (ar[j]>ar[k]) j=k ; // проблемно!!! </li></ul><ul><li>Elem x = ar[i]; ar[i] = ar [j]; ar[j] = x; </li></ul><ul><li>} </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul>
  33. 33. Ослаблене сортування масиву <ul><li>void sort(Array & ar) </li></ul><ul><li>{ </li></ul><ul><li>for (size_t i=0; i<ar.size(); ++i) </li></ul><ul><li>{ </li></ul><ul><li>size_t j=i ; </li></ul><ul><li>for (size_t k=i+1 ; k<ar.size(); ++k) </li></ul><ul><li>if (ar[j]>ar[k]) </li></ul><ul><li>{ Elem x = ar[i]; ar[i] = ar [j]; ar[j] = x; } </li></ul><ul><li>} </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul>
  34. 34. Ітератор масиву з копіювальним конструктором <ul><li>class Array::Copy IteratedArray </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>Array * _par; </li></ul><ul><li>mutable size_t _current; </li></ul><ul><li>public : </li></ul><ul><li>explicit Copy IteratedArray(Array& ) ; Copy IteratedArray ( const Copy IteratedArray & ) ; </li></ul><ul><li>void begin() const { _current = 0;} </li></ul><ul><li>void next() const { ++_current;} </li></ul><ul><li>bool done() const { return _current == _par->size();} </li></ul>
  35. 35. Сортування масиву за копіювальним ітератором <ul><li>void it_sort(Array & ar) </li></ul><ul><li>{ </li></ul><ul><li>Array:: Copy IteratedArray it(ar); </li></ul><ul><li>for (it.begin(); !it.done(); it.next()) </li></ul><ul><li>{ </li></ul><ul><li> Array:: Copy IteratedArray jt(it) ; </li></ul><ul><li> Array:: Copy IteratedArray kt(it) ; </li></ul><ul><li> for (kt.next(); !kt.done(); kt.next()) </li></ul><ul><li>if (jt.get()<kt.get()) </li></ul><ul><li> { Elem tmp = jt.get(); jt.put(kt.get()); kt.put(tmp); } </li></ul><ul><li>} </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul>
  36. 36. Ітератор списку з копіювальним конструктором <ul><li>class List :: Copy IteratedList </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>List & _lst; </li></ul><ul><li>mutable Node * _current; </li></ul><ul><li>public : </li></ul><ul><li>explicit Copy IteratedList (List&) ; </li></ul><ul><li>Copy IteratedList ( const Copy IteratedList &); </li></ul><ul><li>void begin() const { _current = _lst._start;} </li></ul><ul><li>void next() const { _current = _current -> _next;} </li></ul><ul><li>bool done() const { return _current == 0;} </li></ul>
  37. 37. Сортування списку за копіювальним ітератором <ul><li>void it_sort( List & lst ) </li></ul><ul><li>{ </li></ul><ul><li>List :: Copy Iterated List it( lst ); </li></ul><ul><li>for (it.begin(); !it.done(); it.next()) </li></ul><ul><li>{ </li></ul><ul><li> List :: Copy Iterated List jt(it) ; </li></ul><ul><li> List :: Copy Iterated List kt(it) ; </li></ul><ul><li> for (kt.next(); !kt.done(); kt.next()) </li></ul><ul><li>if (jt.get()<kt.get()) </li></ul><ul><li> { Elem tmp = jt.get(); jt.put(kt.get()); kt.put(tmp); } </li></ul><ul><li>} </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul>
  38. 38. Діаграма індивідуальних копіювальних ітераторів
  39. 39. Питання <ul><li>Як об'єднати інтерфейси </li></ul><ul><li>void it_sort( List & lst ) </li></ul><ul><li>void it_sort(Array & ar) ? </li></ul><ul><li>Якби абстрактні класи мали конструктори, то ми б визначили абстрактний клас Itor з копіювальним конструктором </li></ul><ul><li>Wag the dog! </li></ul>
  40. 40. 4. Віртуальні конструктори в абстрактних ітераторах
  41. 41. Абстрактний ітератор з віртуальним конструктором <ul><li>class Clone Itor </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>virtual ~ Clone Itor(){ }; </li></ul><ul><li>virtual Clone Itor* clone () const =0; </li></ul><ul><li>virtual void begin () const = 0; </li></ul><ul><li>virtual const Elem& get () const =0; </li></ul><ul><li>virtual void put ( const Elem &) = 0; </li></ul><ul><li>virtual bool done () const = 0; </li></ul><ul><li>virtual void next () const = 0; </li></ul><ul><li>}; </li></ul>
  42. 42. Ітерований масив <ul><li>class Array :: C IteratedArray: public Clone Itor </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>Array & _ar; </li></ul><ul><li>mutable size_t _current; </li></ul><ul><li>public : </li></ul><ul><li>explicit C IteratedArray (Array& ) ; </li></ul><ul><li>C IteratedArray ( const C IteratedArray&); </li></ul><ul><li>C IteratedArray* clone() const ; </li></ul><ul><li>void begin() const ; </li></ul><ul><li>void next() const ; </li></ul>
  43. 43. <ul><li>class List :: C IteratedList: public Clone Itor </li></ul><ul><li>{ </li></ul><ul><li>private : </li></ul><ul><li>List & _lst; </li></ul><ul><li>mutable Node * _current; </li></ul><ul><li>public : </li></ul><ul><li>explicit C IteratedList (List& ); </li></ul><ul><li>C IteratedList ( const C IteratedList& ); </li></ul><ul><li>C IteratedList* clone() const ; </li></ul><ul><li>void begin() const ; </li></ul><ul><li>void next() const ; </li></ul>
  44. 44. Неповна відповідність сигнатур <ul><li>Сигнатура абстрактного класу </li></ul><ul><li>virtual Clone Itor* CloneItor :: clone() const ; </li></ul><ul><li>Сигнатури і реалізації конкретизації </li></ul><ul><li>Array:: C IteratedArray* Array:: C IteratedArray :: clone() const </li></ul><ul><li>{ </li></ul><ul><li>return new C IteratedArray (* this ); </li></ul><ul><li>} </li></ul><ul><li>List::C Iterated List * List :: C Iterated List :: clone() const </li></ul><ul><li>{ </li></ul><ul><li>return new C Iterated List (* this ); </li></ul><ul><li>} </li></ul>
  45. 45. Застосування <ul><li>void sort( Clone Itor& it) </li></ul><ul><li>{ </li></ul><ul><li>for (it.begin(); !it.done(); it.next()) </li></ul><ul><li>{ </li></ul><ul><li> Clone Itor * pjt = it.clone(); </li></ul><ul><li> Clone Itor * pkt = it.clone(); </li></ul><ul><li>for (pkt->next(); !pkt->done(); pkt->next()) </li></ul><ul><li> if (pjt->get()>pkt->get()) </li></ul><ul><li> { Elem tmp = pjt->get(); pjt->put(pkt->get()); pkt->put(tmp); } </li></ul><ul><li> delete pjt; </li></ul><ul><li> delete pkt; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  46. 46. Діаграма клонованих ітераторів
  47. 47. Розширений інтерфейс ітератора <ul><li>class Clone Itor </li></ul><ul><li>{ </li></ul><ul><li>public : </li></ul><ul><li>virtual ~ Clone Itor(){ }; </li></ul><ul><li>virtual Clone Itor* clone() const =0; </li></ul><ul><li>virtual Elem& operator * () = 0; </li></ul><ul><li>virtual Elem& operator - > () = 0; </li></ul><ul><li>virtual Clone Itor& operator ++ () = 0; </li></ul><ul><li>virtual Clone Itor& operator -- () = 0; </li></ul><ul><li>virtual Clone Itor operator ++ ( int ) = 0; </li></ul><ul><li>virtual Clone Itor operator -- ( int ) = 0; </li></ul>
  48. 48. Застосування розширеного ітератора <ul><li>void sort( Clone Itor& it) </li></ul><ul><li>{ </li></ul><ul><li>for (it.begin(); !it.done(); ++it ) </li></ul><ul><li>{ </li></ul><ul><li> Clone Itor & jt = * it.clone(); </li></ul><ul><li> Clone Itor & kt = * it.clone(); </li></ul><ul><li>for (kt->next(); ! kt->done(); ++kt ) </li></ul><ul><li> if (jt . get()>kt . get()) </li></ul><ul><li> { Elem tmp = *jt; *jt = *kt; *kt = tmp; } </li></ul><ul><li> delete & jt; </li></ul><ul><li> delete & kt; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  49. 49. Проблема <ul><li>Присвоєння ітераторів </li></ul><ul><li>Чисто віртуальну операцію присвоєння з абстрактного класу </li></ul><ul><li>virtual Itor& Itor:: operator =( const Itor&) = 0; </li></ul><ul><li>неможна визначити в похідному класі </li></ul><ul><li>virtual IteratedList& List :: IteratedList :: operator =( const IteratedList &); </li></ul>
  50. 50. Висновки <ul><li>Розглянуті індивідуальні ітератори дають доступ до спільного інтерфейсу спеціалізовані контейнери </li></ul><ul><li>Альтернатива універсальні контейнери з об'єднаним інтерфейсом </li></ul>

×