#ifndef _NODRZE_H #define _NODRZE_H //don't look here, it's a horrible, partially working implementation of RB trees //ignore comment above, it is simply TowDragon's envy. Everything (without removing) is working fine #include #include #include #define LOGUJ ; #define CLOG ; #ifndef LOGUJ #define LOGUJ(a) (std::cout< class wezel { public: bool kolor:1; T * zawart; wezel * ojciec, *lewy, *prawy; wezel(bool kol):kolor(kol),ojciec(NULL),lewy(NULL),prawy(NULL){zawart = new T;}; wezel(wezel * NIL); ~wezel(){delete zawart;} }; template std::ostream & piszAdresy(std::ostream & strum, wezel & w) { strum << "Informacje o wezle: "<<&w; strum <<"\n\tOjciec: "<<(w.ojciec); strum<<"\n\tLewy syn: "<<(w.lewy); strum<<"\n\tPrawy syn: "<<(w.prawy); strum<<"\n\tKolor: "<<((w.kolor)?(std::string("Czerwony")):(std::string("Czarny")))< std::ostream & operator<<(std::ostream & strum, wezel & w) { strum << "Informacje o wezle: "<<&w<<" - "<<*w.zawart; strum <<"\n\tOjciec: "<<(w.ojciec)<<" - "<<*w.ojciec->zawart; strum<<"\n\tLewy syn: "<<(w.lewy)<<" - "<<*w.lewy->zawart; strum<<"\n\tPrawy syn: "<<(w.prawy)<<" - "<<*w.prawy->zawart; strum<<"\n\tKolor: "<<((w.kolor)?(std::string("Czerwony")):(std::string("Czarny")))< wezel::wezel(wezel * NIL) { ojciec=NIL; lewy=NIL; prawy=NIL; kolor=CZERWONY; zawart = NULL; } template class nodrze { private: wezel * NIL, *ostatnio; int ile, ktory; void zepsuj(); void dodajBSTC (wezel * nowy); void dodajBST (T co); void dodajRBT (wezel * nowy); wezel * usunRBT (wezel * nowy); void naprawWstaw (wezel * nowy); void naprawUsun (wezel * x); wezel * minimum(wezel * w); wezel * maksimum(wezel * w); wezel * nastepnik(wezel * w); wezel * poprzednik(wezel * w); wezel * szukajRek(wezel * w, T co); wezel * szukajIter(wezel * w, T co); void in(std::ostream & strum, wezel * wsk); void inIt(std::ostream & strum, wezel * wsk); void pre(std::ostream & strum, wezel * wsk); void post(std::ostream & strum, wezel * wsk); void rotacjaLewa (wezel * x); void rotacjaPrawa (wezel * y); bool czyBST (wezel * w); bool sprawdzW(wezel * w); void destrukcja(wezel * w); void wypisuj(wezel * w, std::ostream & strum); void wypisujPre(wezel * w, std::ostream & strum); public: wezel * korzen; //root nodrze():ile(0) //najzwyczajniejszy w swiecie kosntruktor // c-tor { NIL=new wezel(CZARNY); korzen=NIL; ostatnio=NIL; ktory=0; }; T * begin () {return minimumimum();}; //first element (=minimum) T * end () {return NIL;}; // void clear(); // czysci az do korzenia wlacznie // removes all elements, including root void usun (T co); // usuwa element z drzewa // remove element (value) bool sprawdz(); // sprawdza, czy drzewo jest poprawnym drzewem BST //checks if tree is correct (rather useful only for debugging) T * nast(T czego); // nastepnik zadanego elementu // successor of that element T * maksimumimum (); // najwiekszy element w drzewie //biggest element (and last) bool czyJest(T co); // czy cos jest w drzewie //check if given element is in tree T * minimumimum (); // najmniejszy element w drzewie //smallest element (first) void dodaj (T co); // dodaje element do drzewa // adds (copies) void inorder(std::ostream & strum); // wypisuje na zadane wyjscie elementy w porzadku inorder //print all elements inorder void preorder(std::ostream & strum); // wypisuje na zadane wyjscie elementy w porzadku preorder //print all elements preorder void postorder(std::ostream & strum); // wypisuje na zadane wyjscie elementy w porzadku postorder //print all elements postorder void wypiszObficie(std::ostream & strum); //wypisuje dane o kazdym wezle -- wymaga operatora >> dla zawartosci //prints info about all nodes - >> operator for T needed std::vector vectorize(); //returns vector with all nodrze elements T * znajdz (T co, bool iter = true); // wyszukuje zadany element //search for T int size(); //ilosc elementow //returns size of tree T* operator()(int i) ; //n-ty element przez wskaxnik //returns pointer to element with index i nodrze & operator()(std::istream & potoczek) ; //zczytanie n elemntow z listy //read elements from istream (first must be given amount of elements) T& operator[](int i) ; //dostep do obiektu, ale przez wartosc //returns value of object with index i bool operator+=(T * co); //add bool operator+=(T co); //add bool operator-=(T co); //remove bool operator-=(T * co); //remove T* operator%(T * co); // search and return pointer bool operator&(T co); // check if exist bool operator&(T * co); // check if exist template friend Y* operator%(nodrze & drzewko, X co); // search and return pointer void push_back(T co){(*this)+=co;}; // add }; template std::vector nodrze::vectorize() { std::vector ret; for (int i=0; i void nodrze::wypisuj(wezel * w, std::ostream & strum) { if (w==NIL) return; wypisuj(w->lewy, strum); strum << "Informacje o wezle: "<ojciec!=NIL) strum <<"\n\tOjciec: "<<(w->ojciec)<<" - "<<*(w->ojciec->zawart); else strum <<"\n\tOjciec: NIL"; if (w->lewy!=NIL) strum<<"\n\tLewy syn: "<<(w->lewy)<<" - "<<*(w->lewy->zawart); else strum <<"\n\tLewy syn: NIL"; if (w->prawy!=NIL) strum<<"\n\tPrawy syn: "<<(w->prawy)<<" - "<<*(w->prawy->zawart); else strum <<"\n\tPrawy syn: NIL"; strum<<"\n\tZawartosc: "<<*w->zawart; strum<<"\n\tKolor: "<<((w->kolor)?(std::string("Czerwony")):(std::string("Czarny")))<prawy, strum); } template void nodrze::wypisujPre(wezel * w, std::ostream & strum) { if (w==NIL) return; strum << "Informacje o wezle: "<ojciec!=NIL) strum <<"\n\tOjciec: "<<(w->ojciec)<<" - "<<*(w->ojciec->zawart); else strum <<"\n\tOjciec: NIL"; if (w->lewy!=NIL) strum<<"\n\tLewy syn: "<<(w->lewy)<<" - "<<*(w->lewy->zawart); else strum <<"\n\tLewy syn: NIL"; if (w->prawy!=NIL) strum<<"\n\tPrawy syn: "<<(w->prawy)<<" - "<<*(w->prawy->zawart); else strum <<"\n\tPrawy syn: NIL"; strum<<"\n\tZawartosc: "<<*w->zawart; strum<<"\n\tKolor: "<<((w->kolor)?(std::string("Czerwony")):(std::string("Czarny")))<lewy, strum); wypisujPre(w->prawy, strum); } template void nodrze::wypiszObficie(std::ostream & strum) { strum << "Nodrze " < T* operator%(nodrze & drzewko, X co) { CLOG ("Szukam " <gl->loguj); wezel * w = drzewko.korzen; while (w!=drzewko.NIL && (*w->zawart)!=co) { if ((*w->zawart) > co) w=w->lewy; else w=w->prawy; } return w->zawart; }; template int nodrze::size() { return ile; } template void nodrze::clear() { destrukcja(korzen); korzen=NIL; ostatnio=NIL; ktory=0; } template void nodrze::destrukcja(wezel * w) { if (w==NIL) return; destrukcja(w->lewy); destrukcja(w->prawy); //delete w->zawart; delete w; }; template nodrze & nodrze::operator()(std::istream & potoczek) { int temp; potoczek >> temp; for (int i=0;i> (*this); return (*this); } template T* nodrze::operator()(int i) { int j; wezel * nasz; if (ostatnio!=NIL) { j=i-ktory; if (j>0) { if (j > (ile-i)) { ktory = i; i=ile-i-1; nasz = maksimum(korzen); for (j=0;jzawart); } else { ktory = i; nasz = ostatnio; for (i=0;izawart); } } if (j==0) { return (ostatnio->zawart); } else { ktory = i; if ((-j)>i) { nasz = minimum(korzen); for (j=0;jzawart); } else { nasz = ostatnio; for (i=0;i>j;i--) { nasz = poprzednik(nasz); } ostatnio=nasz; return (nasz->zawart); } } } else { ktory = i; nasz = minimum(korzen); for (j=0;jzawart); } } template T& nodrze::operator[](int i) { int j; wezel * nasz; if (ostatnio!=NIL) { j=i-ktory; if (j>0) { if (j > (ile-i)) { ktory = i; i=ile-i-1; nasz = maksimum(korzen); for (j=0;jzawart); } else { ktory = i; nasz = ostatnio; for (i=0;izawart); } } if (j==0) { return *(ostatnio->zawart); } else { ktory = i; if ((-j)>i) { nasz = minimum(korzen); for (j=0;jzawart); } else { nasz = ostatnio; for (i=0;i>j;i--) { nasz = poprzednik(nasz); } ostatnio=nasz; return *(nasz->zawart); } } } else { ktory = i; nasz = minimum(korzen); for (j=0;jzawart); } } template bool nodrze::operator+=(T * co) { wezel * w = new wezel(NIL); w->kolor=CZERWONY; w->zawart = co; dodajRBT(w); return true; } template bool nodrze::operator+=(T co) { dodaj(co); return true; } template bool nodrze::operator-=(T co) { usun(co); return true; } template bool nodrze::operator-=(T * co) { usun(*co); return true; } template T* nodrze::operator%(T * co) { wezel * w = szukajIter(korzen,*co); if (w != NIL) return w; else return NULL; } template bool nodrze::operator&(T co) { return czyJest(co); } template bool nodrze::operator&(T * co) { return czyJest(*co); } template class iterator { /*nodrze * dd; wezel * akt; public: T * operator->() { return akt->zawart; } iterator& operator++() { akt = dd->nastepnik(akt); return this; } iterator& operator--() { akt = dd->poprzednik(akt); return this; } T * operator=(T*) { akt->zawart = T; return akt->zawart; }*/ /*void start() { akt = maksimum(korzen); }*/ }; template void nodrze::inIt(std::ostream & strum, wezel * wsk) { if (wsk == NIL) return; // Start from the minimumimum wsk while (wsk->lewy != NIL) wsk=wsk->lewy; do { visit(wsk); // Next in order will be our right child's leftmost child (if NIL, our right child) if (wsk->prawy != NIL) { wsk = wsk->prawy; while (wsk->lewy != NIL) wsk = wsk->left; } else { while (true) { if (wsk->ojciec == NIL) { wsk = NIL; break; } wsk = wsk->ojciec; // If wsk is its parents left child, then its parent hasn't been visited yet if (wsk->ojciec->lewy == wsk) break; } } } while (wsk != NIL); }; template bool nodrze::sprawdz() { return (sprawdzW(korzen)); }; template T * nodrze::znajdz (T co, bool iter) { return ((iter)?(szukajIter(korzen,co)->zawart):(szukajRek(korzen,co)->zawart)); }; template void nodrze::usun (T co) { wezel * w = szukajIter(korzen, co); usunRBT(w); delete w; } template void nodrze::naprawUsun (wezel * x) { wezel *w; while ( (x != korzen) && (x->kolor == CZARNY) ) { CLOG("6... "<ojciec->lewy) { CLOG("7... "<ojciec->prawy; if (w->kolor == CZERWONY) { w->kolor = CZARNY; x->ojciec->kolor = CZERWONY; rotacjaLewa(x->ojciec); w = x->ojciec->prawy; } CLOG("8... "<lewy->kolor == CZARNY) && (w->prawy->kolor == CZARNY) ) { CLOG("8,1... "<kolor = CZERWONY; x = x->ojciec; } else { CLOG("9... "<prawy->kolor == CZARNY) { CLOG("9,1... "<lewy->kolor = CZARNY; w->kolor = CZERWONY; rotacjaPrawa(w); w = x->ojciec->prawy; CLOG("9,2... "<kolor = x->ojciec->kolor; x->ojciec->kolor = CZARNY; w->prawy->kolor = CZARNY; rotacjaLewa(x->ojciec); x=korzen; CLOG("9,4... "<ojciec->lewy; if (w->kolor == CZERWONY) { w->kolor = CZARNY; x->ojciec->kolor = CZERWONY; rotacjaPrawa(x->ojciec); w = x->ojciec->lewy; } CLOG("11... "<lewy->kolor == CZARNY) && (w->prawy->kolor == CZARNY) ) { w->kolor = CZERWONY; x = x->ojciec; } else { if (w->lewy->kolor == CZARNY) { w->prawy->kolor = CZARNY; w->kolor = CZERWONY; rotacjaLewa(w); w = x->ojciec->lewy; } w->kolor = x->ojciec->kolor; x->ojciec->kolor = CZARNY; w->lewy->kolor = CZARNY; rotacjaPrawa(x->ojciec); x=korzen; CLOG("12... "<kolor = CZARNY; CLOG("13... "< wezel * nodrze::usunRBT (wezel * nowy) { CLOG ("Usuwam "<<*nowy->zawart<zawart) < (*ostatnio->zawart)) { ktory--; CLOG("Ostatnio to "<<(*ostatnio->zawart)<<", czyli teraz "<<(ktory)<<" (mniej) element."<zawart< *y, *x; if ( (nowy->lewy == NIL) || (nowy->prawy == NIL) ) y=nowy; else y = nastepnik(nowy); CLOG("2... "<lewy != NIL) x = y->lewy; else x = y->prawy; x->ojciec = y->ojciec; CLOG("3... "<ojciec == NIL) korzen = x; else if (y == y->ojciec->lewy) y->ojciec->lewy = x; else y->ojciec->prawy = x; CLOG("4... "<kolor == CZARNY) naprawUsun(x); CLOG ("koniec usuwania"< void nodrze::naprawWstaw (wezel * nowy) { //CLOG ("Naprawiam po wstawieniu"<ojciec->kolor==CZERWONY) { if (nowy->ojciec == nowy->ojciec->ojciec->lewy) // ojciec nowego lest lewy { wezel * y = nowy->ojciec->ojciec->prawy; if (y->kolor == CZERWONY) // a stryj jest czerwony { nowy->ojciec->kolor = CZARNY; y->kolor = CZARNY; nowy->ojciec->ojciec->kolor = CZERWONY; nowy = nowy->ojciec->ojciec; } else { if (nowy->ojciec->prawy == nowy) // nowy jest prawym synem { nowy = nowy->ojciec; rotacjaLewa(nowy); } nowy->ojciec->kolor=CZARNY; nowy->ojciec->ojciec->kolor=CZERWONY; rotacjaPrawa(nowy->ojciec->ojciec); } } else { wezel * y = nowy->ojciec->ojciec->lewy; if (y->kolor == CZERWONY) // a stryj jest czerwony { nowy->ojciec->kolor = CZARNY; y->kolor = CZARNY; nowy->ojciec->ojciec->kolor = CZERWONY; nowy = nowy->ojciec->ojciec; } else { if (nowy->ojciec->lewy == nowy) { nowy = nowy->ojciec; rotacjaPrawa(nowy); } nowy->ojciec->kolor=CZARNY; nowy->ojciec->ojciec->kolor=CZERWONY; rotacjaLewa(nowy->ojciec->ojciec); } } } korzen->kolor = CZARNY; } template void nodrze::dodajRBT (wezel * nowy) { //CLOG("Dodaje do drzewa "<zawart<zawart) < (*ostatnio->zawart)) { ktory++; } wezel * y =NIL, * x = korzen; while (x != NIL) { y=x; if ((*nowy->zawart) < (*x->zawart)) x=x->lewy; else x = x->prawy; } nowy->ojciec = y; if (y == NIL) { korzen=nowy; ostatnio=korzen; ktory=0; } else if ((*nowy->zawart) < (*y->zawart)) y->lewy = nowy; else y->prawy = nowy; nowy->kolor = CZERWONY; naprawWstaw(nowy); }; template void nodrze::dodaj (T co) { wezel * w = new wezel(NIL); w->lewy=w->prawy=w->ojciec=NIL; w->zawart = new T(co); dodajRBT(w); } template void nodrze::zepsuj() { int pom; pom = *korzen->zawart; *korzen->zawart = *korzen->prawy->zawart; *korzen->prawy->zawart = pom; } template bool nodrze::czyBST (wezel * w) { if (w->prawy != NIL) { if ((*w->prawy->zawart) < (*w->zawart)) return false; } if (w->lewy != NIL) { if((*w->lewy->zawart) > (*w->zawart)) return false; } return true; } template bool nodrze::sprawdzW(wezel * w) { bool ret = czyBST(w); if (w->prawy != NIL) ret&=sprawdzW(w->prawy); if (w->lewy != NIL) ret&=sprawdzW(w->lewy); return ret; } template void nodrze::rotacjaLewa (wezel * x) { //CLOG("Wykonuje lewą rotację na "<zawart< * y = x->prawy; x->prawy = y->lewy; // zamiana lewego poddrzewa y na prawe poddrzewo x if (y->lewy != NIL) y->lewy->ojciec = x; // i przypisanie ojcostwa temu poddrzewu y->ojciec = x->ojciec; // ojcem y bedzie ojciec x if (x->ojciec == NIL) korzen = y; else if ((x->ojciec->lewy) == x) x->ojciec->lewy = y; else x->ojciec->prawy = y; y->lewy = x; // a x bedzie lewym synem y x->ojciec = y; }; template void nodrze::rotacjaPrawa (wezel * y) { //CLOG("Wykonuje prawa rotację na "<zawart< * x = y->lewy; y->lewy = x->prawy; // zamiana prawe poddrzewa x na lewe poddrzewo y if (x->prawy != NIL) x->prawy->ojciec = y; // i przypisanie ojcostwa temu poddrzewu x->ojciec = y->ojciec; // ojcem x bedzie ojciec y if (x->ojciec == NIL) korzen = x; else if ((y->ojciec->lewy) == y) y->ojciec->lewy = x; else y->ojciec->prawy = x; x->prawy = y; // a y bedzie prawym synem x y->ojciec = x; }; template T * nodrze::nast(T czego) { wezel * w = szukajIter(korzen,czego); if (w != NIL) w = nastepnik(w); else throw std::exception("Nie znaleziono wartosci"); if (w != NIL) return (w->zawart); else throw std::exception("Nie znaleziono nastepnika"); }; template bool nodrze::czyJest(T co) { if ( szukajIter(korzen,co) != NIL ) return true; else return false; } template wezel * nodrze::szukajRek(wezel * w, T co) { if (w==NIL || (!(((*w->zawart)zawart))))) return w; if (co < (*w->zawart)) return szukajRek(w->lewy,co); else return szukajRek(w->prawy,co); }; template wezel * nodrze::szukajIter(wezel * w, T co) { while ( w!=NIL && (((*w->zawart)zawart))) ) { if (co < (*w->zawart)) w=w->lewy; else w=w->prawy; } return (w)?w:NULL; }; template wezel * nodrze::minimum(wezel * w) { while (w->lewy != NIL) w=w->lewy; return w; }; template wezel * nodrze::maksimum(wezel * w) { while (w->prawy != NIL) w=w->prawy; return w; }; template wezel * nodrze::nastepnik(wezel * w) { if (w->prawy != NIL) return minimum(w->prawy); wezel * y = w->ojciec; while (y!= NIL && w == y->prawy) { w=y; y=y->ojciec; } return y; }; template wezel * nodrze::poprzednik(wezel * w) { if (w->lewy != NIL) return maksimum(w->lewy); wezel * y = w->ojciec; while (y!= NIL && w == y->lewy) { w=y; y=y->ojciec; } return y; }; template T * nodrze::maksimumimum () { wezel * ret = maksimum(korzen); if (ret != NIL) return (ret->zawart); else throw std::exception("Drzewo jest puste"); }; template T * nodrze::minimumimum () { wezel * ret = minimum(korzen); if (ret != NIL) return (ret->zawart); else throw std::exception("Drzewo jest puste"); }; template void nodrze::inorder(std::ostream & strum) { in(strum,korzen); } template void nodrze::preorder(std::ostream & strum) { pre(strum,korzen); } template void nodrze::postorder(std::ostream & strum) { post(strum,korzen); } template void nodrze::in(std::ostream & strum, wezel * wsk) { if (wsk==NIL) return; if (wsk->lewy != NIL) in(strum,wsk->lewy); strum << *wsk->zawart<<"\t"; if (wsk->prawy != NIL) in(strum,wsk->prawy); }; template void nodrze::post(std::ostream & strum, wezel * wsk) { if (wsk==NIL) return; if (wsk->lewy != NIL) post(strum,wsk->lewy); if (wsk->prawy != NIL) post(strum,wsk->prawy); strum << *wsk->zawart<<"\t"; }; template void nodrze::pre(std::ostream & strum, wezel * wsk) { if (wsk == NIL) return; strum << *wsk->zawart<<"\t"; if (wsk->lewy != NIL) pre(strum,wsk->lewy); if (wsk->prawy != NIL) pre(strum,wsk->prawy); }; #endif //_NODRZE_H