220 likes | 385 Views
Objektovo - Orientované Programovanie. Binárne vyhľadávacie stromy. Reprezentácia stromov ako v halde - v jednorozmernom poli: každý prvok reprezentuje jeden vrchol stromu: prvý prvok je koreň í-ty vrchol má synov na indexoch 2*i a 2*i+1
E N D
Objektovo - Orientované Programovanie Binárne vyhľadávacie stromy
Reprezentácia stromov • ako v halde - v jednorozmernom poli: • každý prvok reprezentuje jeden vrchol stromu: • prvý prvok je koreň • í-ty vrchol má synov na indexoch 2*i a 2*i+1 • treba evidovať "diery" - miesta, ktoré nereprezentujú vrcholy • pole vrcholov, kde vrchol obsahuje info a indexy do poľa pre ľavého a pravého syna pole vrcholov - každý vrchol má spájaný zoznam synov (táto reprezentácia by sa dala použiť aj na všeobecný strom)
Dynamická štruktúra pre binárny strom type TStrom = class info:prvok; l,p:TStrom; constructor Create(i:prvok; nl,np:TStrom); function text:string; virtual; end; constructor TStrom.Create(i:prvok; nl, np: TStrom); begin info:=i; l:=nl; p:=np; end;
function TStrom.text:string; begin Result:=IntToStr(info); end; var s:TStrom; ... s:=nil; // prázdny strom s:=TStrom.Create(1,nil,nil); s:=TStrom.Create(1,TStrom.Create(2,nil,nil),TStrom.Create(3,nil,nil));
Základné algoritmy • na navštívenie postupne všetkých vrcholov (napr. výpis hodnôt) • pre N vrcholový binárny strom N! možných prechodov, len niektoré z nich sú rozumné => 3 algoritmy prechádzania vrcholmi stromov: • Preorder - najprv informáciu vo vrchole, potom v ľavom podstrome a na záver v pravom
Inorder - najprv spracuje ľavý podstrom, potom info vo vrchole a na záver v pravom podstrome • Postorder - najprv spracuje ľavý, potom pravý podstrom a na záver info v samotnom vrchole • naprogramujeme metódy preorder, inorder, postorder - tieto postupne spracujú všetky vrcholy podľa špecifického poradia
nasledujúce metódy vypíšu všetky vrcholy (do Memo1) v rôznych poradiach podľa príslušných algoritmov: procedure TStrom.vypis; // vypíše len jeden vrchol = koreň begin Form1.Memo1.Lines.Add(text); end; procedure TStrom.preorder; begin vypis; if l<>nil then l.preorder; if p<>nil then p.preorder; end;
procedure TStrom.inorder; begin if l<>nil then l.inorder; vypis; if p<>nil then p.inorder; end; procedure TStrom.postorder; begin if l<>nil then l.postorder; if p<>nil then p.postorder; vypis; end;
Ďalšie pojmy • otec = predchodca; syn = nasledovník • dva stromy sú podobné, ak majú rovnakú štruktúru (rovnaký tvar) • jeden strom je kópiou druhého, ak sú podobné a majú rovnaký obsah vrcholov • úrovne: každý vrchol v strome má svoju úroveň (level):
koreň je v úrovni 0; jeho synovia sú úrovne 1 • synovia vrcholu úrovne U majú úroveň U+1 • v každej úrovni U je max. 2U vrcholov • úplný strom úrovne U má vo všetkých úrovniach (0 až U) maximálny počet vrcholov • šírka stromu = najväčší počet vrcholov na jednej úrovni
Binárny vyhľadávací strom • všetky hodnoty naľavo od otca sú menšie ako otec • všetky hodnoty napravo od otca sú väčšie ako otec • všetky podstromy sú tiež BVS • výpis pomocou algoritmu inorder vypíše utriedenú postupnosť
definíciu stromu rozdelíme na definíciu vrcholu stromu: type prvok = integer; TVrchol = class info:prvok; l,p:TVrchol; constructor Create(i:prvok; nl,np:TVrchol); function text:string; virtual; end;
constructor vrchol.Create(i:prvok; nl,np:TVrchol); begin info:=i; l:=nl; p:=np; end; function vrchol.text:string; begin Result:=IntToStr(info); end;
a trieda strom obsahuje len smerník na koreň stromu: type TBVStrom = class private koren:TVrchol; public constructor Create; procedure vypis; function hladaj(i:prvok):TVrchol; procedure vloz(i:prvok); procedure zrus(i:prvok); end;
constructor TBVStrom.Create; begin koren:=nil; end; procedure TBVStrom.vypis; procedure vypis1(s:TVrchol); begin if s=nil then exit; Form1.Memo1.Lines.Add(s.text); vypis1(s.l); vypis1(s.p); end; begin vypis1(koren); end;
Hľadanie v binárnom vyhľadávacom strome • algoritmus sa postupne vnára do stromu, pričom na základe hodnoty vo vrchole sa rozhoduje, či pokračuje vľavo alebo vpravo • keď nenájde vrchol, vráti nil
hľadanie v BVS: function TBVStrom.hladaj(i:prvok):TVrchol; begin Result:=koren; while (Result<>nil) and (Result.info<>i) do if Result.info>i then Result:=Result.l else Result:=Result.p; end;
Vloženie nového prvku tak, aby strom ostal BVS • najprv nájde miesto, kam by sa dal zavesiť nový vrchol (ako list), pričom sa podľa hodnoty vo vrchole rozhoduje, či pokračuje vľavo alebo vpravo • ak vrchol s danou hodnotou nájde, tak do stromu nový vrchol nevloží, ale skončí:
vloženie novej hodnoty do BVS: procedure TBVStrom.vloz(i:prvok); procedure vloz1(var s:TVrchol); begin if s=nil then s:=vrchol.Create(i,nil,nil) else if s.info=i then // nič, lebo sa našiel else if s.info>i then vloz1(s.l) else vloz1(s.p) end; begin vloz1(koren); end;
Rušenie vrcholu tak, aby ostal strom BVS • problém je iba s rušením vrcholu, ktorý má oboch synov - daný algoritmus nájde minimum v pravom podstrome vrcholu, toto minimum vyhodí a jeho hodnotu dá namiesto rušeného vrcholu:
vyhodenie vrcholu z BVS: procedure TBVStrom.zrus(i:prvok); function zrusmin(var s:TVrchol):prvok; var q:TVrchol; begin if s.l=nil then begin Result:=s.info; q:=s; s:=s.p; q.Free end else Result:=zrusmin(s.l) end;
procedure zrus1(var s:TVrchol); begin if s=nil then // nič else if s.info>i then zrus1(s.l) else if s.info<i then zrus1(s.p) else if (s.l=nil) and (s.p=nil) then begin s.Free; s:=nil end else if s.l=nil then s:=s.p else if s.p=nil then s:=s.l else s.info:=zrusmin(s.p) // z pravého podstromu minimálny prvok end; begin zrus1(koren); end;