Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 1/53 Pole, množina, tabulka Ing. Josef Vogel, CSc Katedra softwarového inženýrství Katedra teoretické informatiky, Fakulta informačních technologii, ČVUT v Praze Karel Müller, Josef Vogel, 2011 Programování a algoritmizace 2, BI-PA2, 2011, Přednáška 11 BI-PA2 Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti
Témata ADT pole (Array) jednorozměrné a vícerozměrné pole mapovací funkce pole přístupové vektory pro vícerozměrné pole ADT množina (Set) základní a množinové operace implementace pomocí charakteristického vektoru implementace neseřazeným polem implementace seřazeným polem ADT tabulka (Table, Map) základní operace implementace tabulkou s přímým přístupem implementace neseřazeným polem implementace seřazeným polem Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 2/53
ADT Pole Pole (array) je sekvenční kontejner, který organizuje prvky v n dimenzích a umožňuje náhodný přístup (random acces) s konstantní složitostí k prvkům pomocí n-tice indexů Pole je obecně dáno: typem prvků počtem dimenzí dolní a horní mezí indexu pro každou dimenzi (množiny indexů jsou uspořádané) Typ N-rozměrného pole lze specifikovat výrazem kde array [d 1.. h 1, d 2.. h 2,... d N.. h N ] of T T je typ prvků pole N je počet dimenzí (indexů) d i je dolní mez i-tého indexu h i je horní mez i-tého indexu Pro počet prvků pole platí M = 1 i N (h i d i + 1) Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 3/53
Jednorozměrné pole Vnitřní reprezentací jednorozměrného pole typu array [d.. h] of T je vždy souvislý úsek paměti, ve kterém jsou prvky pole uloženy jeden za druhým Vnitřní reprezentaci pole lze považovat za pole typu array [0.. h-d+1] of T Mapovací funkce map pole typu array [d.. h] of T mapuje prvky tohoto pole na prvky pole vnitřní reprezentace, tj. indexu i z intervalu d až h přiřazuje index vnitřní reprezentace z intervalu 0 až h-d+1 Pro pole typu je array [d.. h] of T map(i) = i - d Je-li dolní mez indexu 0, pak pro mapovací funkci platí map(i) = i (např. v jazyku C, C++) Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 4/53
p11\array\array.h Jednorozměrné pole Pro ADT jednorozměrné pole mohou být specifikovány další operace, jako například rozšíření (zvýšení počtu prvků) Šablona pro ADT jednorozměrné rozšiřitelné pole (s hlubokou kopií) byla uvedena v příkladech k přednášce 7, zde budeme používat její deklaraci: template <class Elem> class Array { public: explicit Array(int=2); Array(const Array&); ~Array(); int length() const {return len; Elem& operator[](int); const Elem& operator[](int) const; Array& operator=(const Array&); void extend(int); private: Elem* array; int len; void copy(const Array&); ; Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 5/53
Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 6/53 Vícerozměrné pole Typ vícerozměrného (N>1) pole lze specifikovat výrazem array [d 1.. h 1, d 2.. h 2,... d N.. h N ] of T Vnitřní reprezentací vícerozměrného pole může (mohou) být: souvislý úsek paměti, ve kterém jsou prvky umístěny po řádcích (nejrychleji se mění poslední index) souvislý úsek paměti, ve kterém jsou prvky umístěny po sloupcích (nejrychleji se mění první index) přístupové (Iliffe-ovy) vektory Příklad pro pole a typu array [1..3, 1..2] of T po řádcích a 1,1 a 1,2 a 2,1 a 2,2 a 3,2 a 3,2 po sloupcích a 1,1 a 2,1 a 1,2 a 2,2 a 1,3 a 2,3 přístupový vektor a 1,1 a 1,2 a 2,1 a 2,2 a 3,1 a 3,2
Mapovací funkce pole Umístění prvků pole typu array [d 1.. h 1, d 2.. h 2,... d N.. h N ] of T v souvislém úseku paměti array [0.. M-1] of T kde M je počet prvků pole (viz slajd 2) určuje mapovací funkce, která každé N-tici indexů přiřazuje index z intervalu 0 až M-1 Příklady mapovací funkce pro N = 1, 2, 3 a umístění po řádcích : array [d.. h] of T map(i) = i d array [d 1.. h 1, d 2.. h 2 ] of T map(i 1, i 2 ) = (i 1 d 1 )n 2 + (i 2 d 2 ) kde n 2 = h 2 d 2 + 1 array [d 1.. h 1, d 2.. h 2, d 3.. h 3 ] of T map(i 1, i 2, i 3 ) = (i 1 d 1 )n 2 n 3 + (i 2 d 2 )n 3 + (i 3 d 3 ) kde n 2 = h 2 d 2 + 1, n 3 = h 3 d 3 + 1 Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 7/53
p11\matrix\matrix.h Příklad matice uložená po řádcích Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 8/53 Příklad šablony pro dvojrozměrné (dynamicky alokované) pole, kde parametry konstruktoru je stanoven počet řádků a počet sloupců (dolní meze indexu v obou dimenzích jsou 0): template <class Elem> class Matrix { public: Matrix(int, int); Matrix(const Matrix&); ~Matrix(); int getrows() const {return rows; int getcols() const {return cols; Elem& operator()(int, int); const Elem& operator()(int, int) const; Matrix& operator=(const Matrix&); Matrix operator+(const Matrix&) const; private: Elem* array; int rows, cols; void copy(const Matrix&); ;
p11\matrix\main.cpp Příklad matice uložená po řádcích Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 9/53 Příklad použití: int main() { try { int r=0, s=0; cout << "zadej pocet radku a pocet sloupcu: "; cin >> r >> s; Matrix<int> m1(r, s), m2(r,s), m3(r,s); cout << "zadej prvni matici " << endl; cin >> m1; cout << "zadej druhou matici " << endl; cin >> m2; m3 = m1+m2; cout << "soucet matic je\n"; cout << m3 << endl; catch (const char* s) {cout << s << endl; system("pause"); return 0;
p11\array\main.cpp Přístupové vektory šablona Array Pro reprezentaci vícerozměrného pole pomocí přístupových vektorů můžeme použít šablonu rozšiřitelného pole Array (viz slajd 4) Příklad pro dvojrozměrné pole 3x2: typedef Array<int> Vector; typedef Array<Vector> Matrix; int main() { Matrix a(3); // parametrem konstruktoru je dán počet řádků... // počet sloupců je dán implicitní hodnotou par. konstr. Array 3 2 a 1,1 a 1,2 2 2 a 2,1 a 2,2 a 3,1 a 3,2 Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 10/53
p11\array\main.cpp Přístupové vektory šablona Array K prvkům pole Matrix se přistupuje pomocí přetíženého operátoru [] Příklad: funkce pro výpis prvků void print(ostream& os, const Matrix& m) { int r = m.length(); for (int i=0; i<r; i++) { int s = m[i].length(); for (int j=0; j<s; j++) os << m[i][j] << ' '; os << endl; Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 11/53
p11\array\main.cpp Přístupové vektory šablona Array Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 12/53 Technika přístupových vektorů (šablona Array) umožňuje, aby např. v případě dvojrozměrného pole měly řádky různý počet prvků Příklad int main() { Matrix a(3); // pole 3x2... Vector v(4); a[1] = v;... 3 2 a 1,1 a 1,2 4 2 a 2,1 a 2,2 a 2,3 a 2,4 a 3,1 a 3,2
Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 13/53 ADT Množina V programování se množinou rozumí kontejner prvků typu T, který neobsahuje duplicity (prvky se stejnou hodnotou) a umožňuje alespoň tyto základní operace: vložení prvku do množiny test příslušnosti prvku k množině odebrání prvku Signatura základních operací: init: -> Set ins(_,_): Elem,Set -> Set del(_,_): Elem,Set -> Set incl(_,_): Elem,Set -> bool Někdy jsou potřeba další operace: množinové operace sjednocení, průnik a rozdíl, relační operace rovnost, inkluze atd. výpis množiny vytvoření prázdné množiny vložení prvku do množ. odebrání prvku z množ. test příslušnosti k množ.
Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 14/53 Implementace ADT Množina Probereme několik způsobů implementace množiny Každou implementaci realizujeme pomocí třídy nebo šablony třídy V následující deklaraci jsou uvedeny operace, kterými se budeme zabývat: class Set { public: Set(); // inicializace prázdné množiny void ins(t); // vložení prvku void del(t); // odebrání prvku bool incl(t) const; // test příslušnosti Set operator+(const Set&) const; // sjednocení Set operator*(const Set&) const; // průnik bool operator==(const Set&) const; // test rovnosti bool operator<=(const Set&) const; // test inkluze friend ostream& operator<<(ostream&, const Set&); private:... ; Pro každý způsob implementace odhadneme složitost operací
Implementace ADT Množina Pro implementaci množiny lze použít: charakteristický vektor množiny (bitové pole) neseřazené pole seřazené pole jednosměrný spojový seznam uspořádaný spojový seznam binární vyhledávací strom rozptylovací (hash) tabulku Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 15/53
Implementace množiny charakteristickým vektorem Nejprve něco z matematiky: Mějme nosnou množinu X = {x 1, x 2,... x n. Pro A X definujeme charakteristický vektor χ A jako χ A = {c 1, c 2,... c n, kde c i = 1 pro x i A a c i = 0 jinak, 1 i n. Tvoří-li nosnou množinu interval celých čísel od min do max, pak množinu můžeme implementovat pomocí pole s prvky typu bool a indexy od min do max Pro zjednodušení implementace množinových operací budeme předpokládat min = 0, tzn. použijeme pole s indexy od 0 do max Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 16/53
Implementace množiny charakteristickým vektorem Implementaci operací nejprve popíšeme slovně s použitím této notace: a.pole a.pole[x] n a pole reprezentující charakteristický vektor množiny a prvek pole pro hodnotu x velikost (počet prvků) a.pole (počet prvků množiny je obvykle menší) Základní operace: operace implementace složitost a.ins(x) a.pole[x] = true O(1) a.del(x) a.pole[x] = false O(1) a.incl(x) výsledkem je a.pole[x] O(1) Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 17/53
Implementace množiny charakteristickým vektorem Množinové operace: operace implementace složitost a + b vytvoříme novou množinu kopíí množiny a, do které vložíme každý prvek množiny b O(n a +n b ) a * b a == b a <= b vytvoříme novou prázdnou množinu, do které vložíme každý prvek množiny a, který je obsažen v množině b výsledkem je true, když každý prvek a.pole[i] má stejnou hodnotu jako b.pole[i] výsledkem je true, když každý prvek množiny a je také prvkem množiny b O(n) O(n) O(n) Poznámky: n = max(n a, n b ) složitost provedení operace pro všechny prvky množiny a je O(n a ) Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 18/53
p11\set\set.h Třída Set Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 19/53 Množinu implementovanou charakteristickým vektorem můžeme realizovat třídou Set, ve které použijeme šablonu pro rozšiřitelné pole: // set.h #include "array.h" class Set { public: explicit Set(int=0); void ins(int); void del(int); bool incl(int) const; Set operator+(const Set&) const; Set operator*(const Set&) const; bool operator==(const Set&) const; bool operator<=(const Set&) const; friend ostream& operator<<(ostream&, const Set&); friend Set set(int=-1,...); private: Array<bool> arr; ;
p11\set\set.cpp Metody třídy Set Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 20/53 Set::Set(int m) : arr(m+1) { void Set::ins(int x) { if (x>=arr.length()) arr.extend(max(x+1, 2*arr.length())); try {arr[x] = true; catch (...) { void Set::del(int x) { try {arr[x] = false; catch (...) { bool Set::incl(int x) const { try {return arr[x]; catch (...) {return false;
p11\set\set.cpp Metody třídy Set Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 21/53 Set Set::operator+(const Set& y) const { int nx = arr.length(), ny = y.arr.length(); if (nx<ny) return y + *this; Set res = *this; for (int i=0; i<ny; i++) if (y.incl(i)) res.ins(i); return res; Set Set::operator*(const Set& y) const { int nx = arr.length(), ny = y.arr.length(); if (nx>ny) return y * *this; Set res; for (int i=0; i<nx; i++) if (incl(i) && y.incl(i)) res.ins(i); return res;
p11\set\set.cpp Metody třídy Set Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 22/53 bool Set::operator==(const Set& y) const { int nx = arr.length(), ny = y.arr.length(); if (nx>ny) return y==*this; for (int i=0; i<nx; i++) if (arr[i]!=y.arr[i]) return false; for (int i=nx; i<ny; i++) if (y.arr[i]) return false; return true; bool Set::operator<=(const Set& y) const { int n = arr.length(); for (int i=0; i<n; i++) if (arr[i] &&!y.incl(i)) return false; return true;
Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 23/53 p11\set\set.cpp Metody třídy Set ostream& operator<<(ostream& s, const Set& m) { bool mezera = false; s << '['; for (int i=0, n=m.arr.length(); i<n; i++) if (m.arr[i]) { s << (mezera? " " : "") << i; mezera = true; s<<']'; return s; Set set(int x,...) { va_list ppar; Set res; if (x<0) return res; res.ins(x); va_start(ppar, x); for (;;) { x = va_arg(ppar, int); if (x<0) break; res.ins(x); va_end(ppar); return res;
p11\set\sito.cpp Použití třídy Set Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 24/53 Soubor \p11\set\main1.cpp Soubor \p11\set\sito.cpp ilustruje použití třídy Set pro Eratosthenovo síto const int N = 1000; int main() { int i, j; Set a(n); for (int i=2; i<=n; i++) a.ins(i); int p = 2, pmax = (int)sqrt(n); do { // vypusteni vsech nasobku cisla p for (int i=p+p; i<=n; i+=p) a.del(i); // hledani nejblizsiho cisla k p do { p++; while (!a.incl(p)); while (p<=pmax); cout << a << endl; system("pause"); return 0;
Implementace množiny neseřazeným polem Princip: Prvky množiny se ukládají do neseřazeného pole (dynamicky alokovaného) Slovní popis základních operací: operace implementace složitost a.ins(x) a.del(x) sekvenční hledání prvku s hodnotou x, případně vložení x na první volné místo sekvenční hledání prvku s hodnotou x, pak posun dalších prvků o jedno místo doleva O(n a ) O(n a ) a.incl(x) sekvenční hledání prvku pole s hodnotou x O(n a ) Poznámka: n a je počet prvků množiny a (obvykle je to méně, než počet prvků pole) Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 25/53
Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 26/53 Implementace množiny neseřazeným polem Slovní popis množinových operací: operace implementace složitost a + b a * b a == b a <= b vytvoříme novou množinu kopií množiny a, do které vložíme každý prvek množiny b vytvoříme novou prázdnou množinu, do které vložíme každý prvek množiny a, který je též v množině b výsledkem je true, když množiny mají stejný počet prvků a každý prvek množiny a je též prvkem množiny b výsledkem je true, když každý prvek množiny a je též prvkem množiny b O(n a* n b ) O(n a* n b ) O(n a* n b ) O(n a* n b )
p11\set\arrset.h Šablona třídy ArrSet Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 27/53 template <class T> class ArrSet { public: explicit ArrSet(int=10); void ins(const T&); void del(const T&); bool incl(const T&) const; ArrSet operator+(const ArrSet&) const; ArrSet operator*(const ArrSet&) const; bool operator==(const ArrSet&) const; bool operator<=(const ArrSet&) const; ostream& print(ostream&) const; private: Array<T> arr; // rozsiritelne pole int num; // pocet prvku v mnozine int search(const T&) const; //vrati index prvku nebo -1 ;
p11\set\arrset.h Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 28/53 Šablony metod třídy ArrSet template <class T> ArrSet<T>::ArrSet(int m) : arr(m), num(0) { template <class T> int ArrSet<T>::search(const T& x) const { for (int i=0; i<num; i++) if (arr[i]==x) return i; return -1; template <class T> void ArrSet<T>::ins(const T& x) { if (search(x)>=0) return; if (num>=arr.length()) arr.extend(2*arr.length()); arr[num++] = x;
p11\set\arrset.h Šablony metod třídy ArrSet Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 29/53 template <class T> void ArrSet<T>::del(const T& x) { int k = search(x); if (k<0) return; for (k++; k<num; k++) arr[k-1] = arr[k]; num--; template <class T> bool ArrSet<T>::incl(const T& x) const { return search(x)>=0; template <class T> ArrSet<T> ArrSet<T>::operator+(const ArrSet<T>& y) const { ArrSet<T> res = *this; for (int i=0; i<y.num; i++) res.ins(y.arr[i]); return res;
p11\set\arrset.h Šablony metod třídy ArrSet template <class T> ArrSet<T> ArrSet<T>::operator*(const ArrSet<T>& y) const { ArrSet res; for (int i=0; i<num; i++) if (y.incl(arr[i])) res.ins(arr[i]); return res; template <class T> bool ArrSet<T>::operator==(const ArrSet<T>& y) const { if (num!=y.num) return false; for (int i=0; i<num; i++) if (!y.incl(arr[i])) return false; return true; template <class T> bool ArrSet<T>::operator<=(const ArrSet<T>& y) const { for (int i=0; i<num; i++) if (!y.incl(arr[i])) return false; return true; Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 30/53
Implementace množiny seřazeným polem Princip: Prvky množiny se ukládají do seřazeného pole (dynamicky alokovaného) Slovní popis základních operací: operace implementace složitost a.ins(x) vložení x do seřazeného pole O(n a ) a.del(x) binární hledání prvku s hodnotou x, pak posun dalších prvků o jedno místo doleva O(n a ) a.incl(x) binární hledání prvku pole s hodnotou x O(log(n a )) Poznámka: n a je počet prvků množiny a (obvykle je to méně, než počet prvků pole) Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 31/53
Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 32/53 Implementace množiny seřazeným polem Slovní popis množinových operací: operace implementace složitost a + b a * b a == b a <= b vytvoříme novou množinu kopií množiny a, do které vložíme každý prvek množiny b vytvoříme novou prázdnou množinu, do které vložíme každý prvek množiny a, který je též v množině b výsledkem je true, když množiny mají stejný počet prvků a každý prvek množiny a je též prvkem množiny b výsledkem je true, když každý prvek množiny a je též prvkem množiny b O(n a* log(n b )) O(n a* log(n b )) O(n a* log(n b )) O(n a* log(n b ))
p11\set\srtarrset.h Šablona třídy SrtArrSet Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 33/53 template <class T> class SrtArrSet { public: explicit SrtArrSet(int=10); void ins(const T&); void del(const T&); bool incl(const T&) const; SrtArrSet operator+(const SrtArrSet&) const; SrtArrSet operator*(const SrtArrSet&) const; bool operator==(const SrtArrSet&) const; bool operator<=(const SrtArrSet&) const; ostream& print(ostream&) const; private: Array<T> arr; // rozsiritelne pole int num; // pocet prvku v mnozine int search(const T&) const;// vrati index prvku nebo -1
p11\set\srtarrset.h Šablony metody třídy SrtArrSet Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 34/53 template <class T> SrtArrSet<T>::SrtArrSet(int m) : arr(m), num(0) { template <class T> int SrtArrSet<T>::search(const T& x) const { int d=0, h=num-1, k; while (d<=h) { k = (d+h)/2; if (x<arr[k]) h = k-1; else if (x>arr[k]) d = k+1; else return k; return -1;
p11\set\srtarrset.h Šablony metody třídy SrtArrSet Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 35/53 template <class T> void SrtArrSet<T>::ins(const T& x) { if (search(x)>=0) return; if (num>=arr.length()) arr.extend(2*arr.length()); // zatrideni noveho prvku int k=num-1; while (k>=0 && arr[k]>x) { arr[k+1] = arr[k]; k--; arr[k+1] = x; num++; template <class T> void SrtArrSet<T>::del(const T& x) { int k = search(x); if (k<0) return; for (k++; k<num; k++) arr[k-1] = arr[k]; num--;
p11\set\srtarrset.h Šablony metody třídy SrtArrSet Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 36/53 template <class T> bool SrtArrSet<T>::incl(const T& x) const { return search(x)>=0; template <class T> SrtArrSet<T> SrtArrSet<T>::operator+(const SrtArrSet<T>& y) const { SrtArrSet<T> res = *this; for (int i=0; i<y.num; i++) res.ins(y.arr[i]); return res; template <class T> SrtArrSet<T> SrtArrSet<T>::operator*(const SrtArrSet<T>& y) const { SrtArrSet res; for (int i=0; i<num; i++) if (y.incl(arr[i])) res.ins(arr[i]); return res;
p11\set\srtarrset.h Šablony metody třídy SrtArrSet Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 37/53 template <class T> bool SrtArrSet<T>::operator==(const SrtArrSet<T>& y) const { if (num!=y.num) return false; for (int i=0; i<num; i++) if (!y.incl(arr[i])) return false; return true; template <class T> bool SrtArrSet<T>::operator<=(const SrtArrSet<T>& y) const { for (int i=0; i<num; i++) if (!y.incl(arr[i])) return false; return true;
ADT Tabulka Tabulku (table, map) lze charakterizovat jako zobrazení z množiny klíčů do množiny hodnot ADT Tabulka je asociativní kontejner obsahující dvojice klíč-hodnota Signatura základních operací: init: -> Tab ins(_,_, _): Key,Value,Tab -> Tab del(_,_): Key,Tab -> Tab incl(_,_): Key,Tab -> bool read((_,_): Key,Tab -> Value vytvoření prázdné tabulky vložení prvku s daným klíčem a hodnotou. odebrání prvku s daným klíčem test, zda tabulka obsahuje prvek s daným klíčem čtení hodnoty prvku s daným klíčem Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 38/53
Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 39/53 Implementace ADT Tabulka Pro implementaci tabulky lze použít podobné techniky, jako pro množinu Poznámka: množina je vlastně tabulka, která klíčům přiřazuje hodnoty true nebo false Pro realizaci tabulky použijeme šablonu třídy Následující deklarace ukazuje, jaké metody zavedeme pro operace s tabulkou class Tab { Tab(); // inicializace prázdné tabulky void ins(key, Val); // vložení prvku do tabulky void del(key); // odebrání prvku z tabulky bool incl(key) const; // test existence prvku bool read(key, Val&) const; // čtení hodnoty prvku ;
Implementace ADT Tabulka Pro implementaci tabulky lze použít: pole, jehož indexy jsou klíče (tabulka s přímým přístupem) neseřazené pole seřazené pole jednosměrný spojový seznam uspořádaný spojový seznam binární vyhledávací strom rozptylovací (hash) tabulku Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 40/53
Tabulka s přímým přístupem Jsou-li klíči celá čísla od 0 do max, použijeme pro uložení hodnot pole, jehož indexy jsou klíče Prvek tabulky s klíčem k tedy bude mít hodnotu uloženou v prvku pole a[k] Je třeba rozlišit, zda klíči k odpovídá nějaká hodnota To lze např. tak, že z množiny možných hodnot vyčleníme jednu, která bude znamenat, že klíč nemá přiřazenou žádnou hodnotu (např. pro množinu hodnot typu string to může být prázdný řetězec) Tuto hodnotu označíme none Slovní popis operací: operace implementace složitost a.ins(k,v) a.pole[k] = v O(1) a.del(k) a.pole[k] = none O(1) a.incl(k) výsledkem je true, jestliže a.pole[k] none O(1) a.read(k,x) x = a.pole [k] O(1) Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 41/53
p11\table\diracctab.h Šablona třídy DirAccTab Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 42/53 Parametrem šablony třídy DirAccTab bude typ hodnot V a konstanta none typu V, která bude hodnotou prvku pole v případě, že klíč nemá přiřazenou hodnotu Pro uložení hodnot opět použijeme šablonu třídy realizující rozšiřitelné pole template <class V, V none> class DirAccTab { public: explicit DirAccTab(int=10); void ins(int, const V&); void del(int); bool incl(int) const; bool read(int, V&) const; ostream& print(ostream&) const; private: Array<V> arr; // rozsiritelne pole ;
p11\table\diracctab.h Šablony metod třídy DirAccTab Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 43/53 template <class V, V none> DirAccTab<V,none>::DirAccTab(int m) : arr(m+1) { for (int i=0; i<arr.length(); i++) arr[i] = none; template <class V, V none> void DirAccTab<V,none>::ins(int k, const V& v) { if (k>=arr.length()) arr.extend(max(k+1, 2*arr.length())); try {arr[k] = v; catch (...) { template <class V, V none> void DirAccTab<V,none>::del(int k) { try {arr[k] = none; catch (...) {
p11\table\diracctab.h Šablony metod třídy DirAccTab Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 44/53 template <class V, V none> bool DirAccTab<V,none>::incl(int k) const { try {return arr[k]!=none; catch (...) {return false; template <class V, V none> bool DirAccTab<V,none>::read(int k, V& v) const { try { if (arr[k]!=none) { v = arr[k]; return true; else return false; catch (...) {return false; Použití je v souboru p11\table\main1.cpp
Implementace tabulky neseřazeným polem Do neseřazeného pole se ukládají dvojice klíč-hodnota Slovní popis základních operací: operace implementace složitost a.ins(k,v) vložení dvojice <k,v> na první volné místo O(1) a.del(k) sekvenční hledání prvku s klíčem k, pak posun dalších prvků o jedno místo doleva O(n) a.incl(k) sekvenční hledání prvku pole s klíčem k O(n) a.read(k,x) sekvenční hledání prvku pole s klíčem k a pak uložení hodnoty do proměnné x O(n) Realizovat budeme šablonou třídy ArrTab, která bude mít parametr K označující typ klíčů a V označující typ hodnot Pro dvojice klíč-hodnota zavedeme šablonu třídy TabElem s parametry K a V Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 45/53
Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 46/53 p11\table\arrtab.h Šablona třídy ArrTab template <class K, class V> struct TabElem { K key; V val; TabElem(K k, V v) : key(k), val(v) { TabElem() { ; template <class K, class V> class ArrTab { public: explicit ArrTab(int=10); void ins(const K&, const V&); void del(const K&); bool incl(const K&) const; bool read(const K&, V&) const; ostream& print(ostream&) const; private: Array<TabElem<K,V> > arr; // rozsiritelne pole int num; // pocet prvku v tabulce int search(const K&) const; // vrati index prvku nebo -1 ;
p11\table\arrtab.h Šablony metod třídy ArrTab Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 47/53 template <class K, class V> ArrTab<K,V>::ArrTab(int m) : arr(m), num(0) { template <class K, class V> int ArrTab<K,V>::search(const K& k) const { for (int i=0; i<num; i++) if (arr[i].key==k) return i; return -1; template <class K, class V> void ArrTab<K,V>::ins(const K& k, const V& v) { int j = search(k); if (j>=0) { arr.setat(j, TabElem<K,V>(k,v)); return; if (num>=arr.length()) arr.extend(2*arr.length()); arr[num++] = TabElem<K,V>(k,v);
p11\table\arrtab.h Šablony metod třídy ArrTab Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 48/53 template <class K, class V> void ArrTab<K,V>::del(const K& k) { int j = search(k); if (j<0) return; for (j++; j<num; j++) arr[j-1] = arr[j]; num--; template <class K, class V> bool ArrTab<K,V>::incl(const K& k) const { return search(k)>=0; template <class K, class V> bool ArrTab<K,V>::read(const K& k, V& v) const { int j = search(k); if (j<0) return false; v = arr[j].val; return true;
Implementace tabulky seřazeným polem Do seřazeného pole se ukládají dvojice klíč-hodnota Slovní popis základních operací: operace implementace složitost a.ins(k,v) vložení dvojice <k,v> do seřazeného pole O(n) a.del(k) binární hledání prvku s klíčem k, pak posun dalších prvků o jedno místo doleva O(n) a.incl(k) binární hledání prvku pole s klíčem k O(log(n)) a.read(k,x) binární hledání prvku pole s klíčem k a pak uložení hodnoty do proměnné x O(log(n)) Realizovat budeme šablonou třídy SrtArrTab, která bude mít parametr K označující typ klíčů a V označující typ hodnot Pro dvojice klíč-hodnota zavedeme šablonu třídy TabElem s parametry K a V Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 49/53
Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 50/53 p11\table\srtarrtab.h Šablona třídy SrtArrTab template <class K, class V> struct TabElem { K key; V val; TabElem(K k, V v) : key(k), val(v) { TabElem() { ; template <class K, class V> class SrtArrTab { public: explicit SrtArrTab(int=10); void ins(const K&, const V&); void del(const K&); bool incl(const K&) const; bool read(const K&, V&) const; ostream& print(ostream&) const; private: Array<TabElem<K,V> > arr; // rozsiritelne pole int num; // pocet prvku v tabulce int search(const K&) const; // vrati index prvku nebo -1 ;
p11\table\srtarrtab.h Šablony metod třídy SrtArrTab Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 51/53 template <class K, class V> SrtArrTab<K,V>::SrtArrTab(int m) : arr(m), num(0) { template <class K, class V> int SrtArrTab<K,V>::search(const K& k) const { int d=0, h=num-1, j; while (d<=h) { j = (d+h)/2; if (k<arr[j].key) h = j-1; else if (k>arr[j].key) d = j+1; else return j; return -1;
p11\table\srtarrtab.h Šablony metod třídy SrtArrTab Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 52/53 template <class K, class V> void SrtArrTab<K,V>::ins(const K& k, const V& v) { int j = search(k); if (j>=0) { arr[k] = TabElem<K,V>(k,v); return; if (num>=arr.length()) arr.extend(2*arr.length()); // zatrideni noveho prvku j=num-1; while (j>=0 && arr[j].key>k) { arr[j+1] = arr[j]; j--; arr[j+1] = TabElem<K,V>(k,v); num++; template <class K, class V> void SrtArrTab<K,V>::del(const K& k) { int j = search(k); if (j<0) return; for (j++; j<num; j++) arr[j-1] = arr[j]; num--;
p11\table\srtarrtab.h Šablony metod třídy SrtArrTab Karel Müller, Josef Vogel (ČVUT FIT) Pole, množina, tabulka BI-PA2, 2011, Přednáška 11 53/53 template <class K, class V> bool SrtArrTab<K,V>::incl(const K& k) const { return search(k)>=0; template <class K, class V> bool SrtArrTab<K,V>::read(const K& k, V& v) const { int j = search(k); if (j<0) return false; v = arr[j].val; return true;