Előadást letölteni
Az előadás letöltése folymat van. Kérjük, várjon
1
C++ Standard Template Library
A lista konténer Dudás László Miskolci Egyetem Alkalmazott Informatikai Tanszék
2
Egy rejtett őrszem elem működik a lista két végén.
A lista konténer #include <list> Mi szükségünk listára, ha van egy sokoldalú vektor tárolónk? A vektorok nem kezelik hatékonyan a sorozat elejére és közepére történő beszúrást A lista szerkezete Egy rejtett őrszem elem működik a lista két végén. list<int> L(2,7); 7 L.size()== 2 1
3
A memóriatartalom vizsgálata
char s[]= "book"; list<char> L(s,s+4); // kétszeresen linkelt // lista next prev b o o k őrszem 2
4
Nincs elemáthelyezés, csak mutatómódosítás.
Előnyös alkalmazási terület vector list Elemek indexelt elérése Csak a végén gyakori a hozzáadás és az eltávolítás A tárolóterület hatékony használata – tárolt mutatók nélkül Tetszőleges elérésű iterátorműveletek használata. Az elemek soros bejárása a következő és az előző elemre mutató pointerek segítségével elegendő Gyakori beszúrás, törlés A szomszédos elemek kapcsolódása fontos. A lista konténerek a beszúrást és a törlést bármely pozícióban O(1) időben végzik. Nincs elemáthelyezés, csak mutatómódosítás. 3
5
Konstruktorok, tagfüggvények
Ugyanolyan funkcionalitású konstruktorok és destruktorok léteznek, mint a vector templétben Nincs reserve() és capacity() függvény a memóriakezelésre Nincs [ ] és at() az elemek index alapján való elérésére A többi vector tagfüggvénynek létezik párja a list templétben. A list templét speciális tagfüggvényei L.front() Referenciát ad az első elemre L.push_front() A lista elejéhez ad egy elemet L.pop_front() Törli az elemet a lista elejéről. 4
6
A push_front() és a pop_front() működése
7 L.push_front(9); 9 7 L.pop_front(); 5
7
A push_front() és a pop_front() működése
7 L.push_front(9); 9 7 L.pop_front(); 6
8
További tagfüggvények
Mozgató, rendező, összefésülő függvények Az alábbiakban p, p2, p2b, p2e list< T >:: iterator típusú iterátorok L.splice(p, L2) Beszúrja az L2 listát az L listába a p pozíción kezdve L.splice(p, L2, p2) Áthelyezi az L2 lista p által mutatott elemét p elé az L listába L.splice(p, L2, p2b, p2e) Áthelyezi a [p2b, p2e) intervallum elemeit az L2 listából az L listába a p által mutatott elem elé L.merge(L2) Belefésüli a rendezett L2 lista elemeit a rendezett L listába megtartva az elemek növekvő sorrendjét L.sort() Rendezi az L lista elemeit. 7
9
Splice, sort, merge példaprogram
#include <list> using namespace std; void main(){ int v[]={1,2,3,4},w[]={15,25}; list<int> L1(v,v+4), L2, L3(w,w+2); L2.push_front(30); L2.push_front(20); list<int>:: iterator it1b, it1e, it2; it1b= L1.begin(); it1e= L1.end(); it1b++; it1e--; // L1: 1,2,3,4 it2= L2.begin(); ++it2; // L2: 20,30 L2.splice(it2,L1,it1b,it1e); // L2: 20,2,3,30 L2.sort(); // L2: 2,3,20,30 L2.merge(L3); // L2: 2,3,15,20,25,30 } // L1: 1,4 L3: üres 8
10
További tagfüggvények ..
A pred az alábbiakban egy logikai függvény mely veszi az L lista egy vagy több elemét és visszaad egy logikai értéket. L.remove(e) Törli a listából az e elemeket L.remove_if(pred) Törli azon elemeket, melyre a logikai függvény igazat ad L.unique() A közvetlenül egymást követő egyforma elemek közül csak az elsőt hagyja meg, a többit törli L.unique(pred) A predikátumot kielégítő, közvetlenül egymást követő két elem közül csak az elsőt hagyja meg, a másikat törli L.reverse() Megfordítja az elemek sorrendjét. 9
11
Example program on unique, remove_if, reverse
#include <iostream> #include <list> using namespace std; bool predicate(char elem){ return elem == 'D'; } void main(){ list<char> L(3, 'D'); // L: 'D','D','D' L.push_front('C'); // L: 'C','D','D','D' L.push_back('E'); // L: 'C','D','D','D','E' L.unique(); // L: 'C','D','E' L.remove_if(predicate); // L: 'C','E' L.reverse(); cout<<L.front()<<L.back()<<endl; // 'E','C' } 10
12
Lista iterátorok #include <list>
Az iterátorok általánossága a ”saját pointer típus” o_p_t átnevezéséből ered az összes konténer templétben, mint a listánál is: A "saját pointer típus" implementáció függő. A typedef miatt minden fajta konténerhez az iterator típust használhatjuk, pl.: list<double>:: iterator it ; template < typename T > class list { public: typedef o_p_t iterator; typedef o_p_t const_iterator; ... }; 11
13
A listák bi-directional iterátorokat használnak
A bi-directional iterátorok lehetővé teszik a lista bejárását előrefelé a next pointerekkel vagy visszafelé a previous pointerekkel. A tetszőleges elérést biztosító iterátorműveletek nem engedélyezettek. Random Access iterator it[ n ] it+= n it-= n it+n n+it it-n it1-it2 it1<it2 it1>it2 it1<=it2 it1>=it2 Bi-directional iterator --it it-- Forward iterator *it it->memb ++it it++ it1==it2 it1!=it2 it1=it2 12
14
Qvíz: Mennyi ‘o’ lesz kiírva?
Példaprogram bi-directional iterátorokkal #include <iostream> #include <list> using namespace std; void main(){ char s[]="book"; list<char> L(s,s+4); list<char>::iterator it1, it2; it1= L.begin(); it2= L.end(); while (it1 != L.end()){ ++it1; --it2; if (*it1 == *it2) cout<<*it1; if (it1 == it2) cout<<*it1; } Qvíz: Mennyi ‘o’ lesz kiírva? 13
15
Megjegyzések A vektorokkal ellentétben, amelyek folytonos memóriaterületet foglalnak el, a listák kettős pointerekkel egymásra hivatkozó elkülönülő memóriaterületeket foglalnak le. A tetszőleges elérést nem implementálták mert nem hatékony, O(n) időt igényel. A dinamikusan kivitelezett elem létrehozás/törlés időigényes. Mivel csak az iterátor léptetése lehetséges, a keresés lassú, O(n) időigényű. Az érvénytelen iterátorokkal óvatosan bánjunk: Az erase() a következő elemre mutató iterátort ad vissza, használjuk azt! list<int> L(5,6); list<int>::iterator it; it = L.begin(); L.erase(it); ++it; //node::NULL it = L.erase(it); 14
Hasonló előadás
© 2024 SlidePlayer.hu Inc.
All rights reserved.