Pemet e Kerkimit Binar Leksion 9
Jan 13, 2016
Perkufizime Një pemë (tree) është një strukturë të dhënash e
kapshme duke filluar nga rrënja (root). Çdo nyje (node) është ose një gjethe (leaf) ose një nyje e brendshme (internal node).
Një nyje e brendshme ka një bir (child)ose më shumë dhe quhet prindi (parent) i nyjeve bija të veta.
Të gjithë bijtë e të njëjtës nyje janë të të njëjtit brez (siblings).
Rrënja është elementi i dallueshëm fillestar ose bazë i një peme. Rrënja është i vetmi element që nuk ka prind.
Perkufizime Një nyje është një njësi reference në një strukturë të
dhënash.
Një gjethe është një element fundor i një peme. Një gjethe është një element pa bij. Ndryshe, një gjethe quhet nyje e jashtme (external node) ose nyje fundore (terminal node).
Një nyje e brendshme është një nyje peme që ka një ose më shumë bij (nyje bija). Një nyje e brendshme është një nyje peme që nuk është gjethe.
Perkufizime Një bir është një element i pemës i cili referohet
nga elementi prind. Çdo element përveç rrënjës është biri i ndonjë prindi.
Prindi i një nyjeje është nyja e pemës konceptualisht sipër ose më afër rrënjës se nyja dhe e cila ka një lidhje (link) me nyjen. Sipas përkufizimit një nyje prind është një nyje e brendshme.
Një lidhje është një referencë, shënjues (pointer) apo mënyrë kapjeje për tek një tjetër pjesë e strukturës së të dhënave. Shpesh, një adresë kujtese.Një nyje në një pemë e cila ka të njëjtin prind me një nyje tjetër quhet e të njëjtit brez me të.
Perkufizime Një pemë binare (binary tree) është një pemë
me të shumtën dy bij për çdo nyje.
Një pemë e kërkimit binar (binary search tree) është një pemë binare ku çdo nënpemë e majtë e nyjes ka çelësa më të vegjël se çelësi (key) i nyjes dhe çdo nënpemë e djathtë ka çelësa më të mëdhenj se çelësi i nyjes.
Një nënpemë është pema bijë e një nyjeje.
Një çelës është pjesa e një grupi të dhënash me anë të së cilës ai (grupi i të dhënave) renditet, indeksohet, referohet etj.
program pemet_BST;{Ky eshte nje program ne Pascal qellimi i te cilit eshte ilustrimi i pemeve te} { kerkimit binar (Binary Search Tree – BST)}constmax_lartesi_BST = 32 {lartesia maksimale e pemes BST – nje peme
BST} {mund te kete maksimalisht 2lartesia elemente} ;type{E deklarojme pemen e kerkimit binar – BST - si tip te dhenash rekursiv }{bazuar ne perkufizimin: Nje peme e kerkimit binar – BST - eshte boshe}{ose perbehet prej rrenjes, nenpemes (BST) se saj te majte dhe te nenpemes }{(BST) se saj te djathte}
tip_elementi = integer;peme = ^nyje_peme;nyje_peme = record
element : tip_elementi; lidhje : array [1..2] of peme;
end;tabele_peme =record
rrenja : peme; numri : integer;end;
varp : peme ;t : tabele_peme;
procedure inicializo (var t : tabele_peme);{kjo procedure krijon nje peme te kerkimit binar – BST-
boshe}begin {inicializo}
t.rrenja := nil;t.numri := 0 ;
end {inicializo};
function bosh (var p : peme) : boolean;{ky funksion kthen true n.q.s. pema BST p eshte boshe
dhe false ne te kundert}begin {bosh}
bosh := p = nil;end {bosh};
procedure bredhje_pararendore (p : peme);{bredhje ne te gjithe elementet e nenpemes p – metoda pararendore
(pre-order)}begin
if not bosh(p) thenbegin
writeln (p^.element);bredhje_pararendore (p^.lidhje[1]) ;bredhje_pararendore (p^.lidhje[2]) ;
endend {bredhje_pararendore};
procedure bredhje_pasrendore (p : peme);{bredhje ne te gjithe elementet e nenpemes p – metoda pasrendore
(post-order)}begin
if not bosh(p) thenbegin
bredhje_pasrendore (p^.lidhje[1]) ;bredhje_pasrendore (p^.lidhje[2]) ;writeln (p^.element);
endend {bredhje_pasrendore};
procedure bredhje_nder_rendore (p : peme);{bredhje ne te gjithe elementet e nenpemes p – metoda nder-
rendore (in-order)}begin
if not bosh(p) thenbeginbredhje_nder_rendore (p^.lidhje[1]) ;writeln (p^.element);bredhje_nder_rendore (p^.lidhje[2]) ;
endend {bredhje_nder_rendore};
function numri (p : peme) : integer;{ky funksion kthen numrin e elementeve te nenpemes p}begin {numri}
if p = nil thennumri := 0
elsenumri := numri (p^.lidhje[1]) + 1 + numri (p^.lidhje[2]);
end {numri};
procedure lexo_BST (var p : peme; var t : tabele_peme);{shton elementet ne nje peme te tipit BST, duke u bazuar pikerisht ne } { cilesite e pemes se kerkimit binar – BST}var{ne elm ruajme elementin per tu shtuar, akoma tregon nese kemi }{ akoma elemente per shqyrtim; ugjet tregon elementi kandidat per t’u }{ shtuar ekziston ne peme apo jo; p eshte shenjuesi mbi elementin e ri }{ per tu shtuar dhe q prindi i tij (nese ka te tille) ne pemen t; drejtimi }{ tregon kahun e vendndodhjes se p (birit te q)}
elm : tip_elementi; akoma, ugjet : boolean; q : peme;drejtimi : integer;
procedure perfto (var elm : tip_elementi; var akoma : boolean);{perftojme elementin e rradhes dhe shqyrtojme nese ka akoma {elemente te tjere}
constfund = -1;
beginreadln (elm);
akoma := elm <> fundend {perfto};
begin{inicializimi}elm := 0;akoma := true;perfto (elm, akoma);while akoma do {derisa te mos kemi si input elm=-1}begin{bredhim pemen me ane te shenjuesit p duke ruajtur ne q prindin e } { p dhe tek drejtimi kahun e zbritjes ne pemen t}
q := nil;p := t.rrenja;ugjet := false;while ((p <> nil) and not(ugjet)) do
if p^.element = elm thenugjet := true {nese elementi tashme ekziston mos
bej asgje} else
beginif p^.element > elm then
drejtimi := 1else
drejtimi := 2;q := p;p := p^.lidhje[drejtimi]
end;
If not(ugjet) then begin
new (p);p^.element := elm;p^.lidhje[1] := nil;p^.lidhje[2] := nil;if q <> nil then
q^.lidhje[drejtimi] := p else
t.rrenja := p; {q=nil dmth shto ne rrenje} t.numri := t.numri +1 ;end ;
perfto (elm, akoma);end;
end {lexo_BST};
begin {MAIN}inicializo (t);p := nil;lexo_BST(p,t) ;p := t.rrenjabredhje_nder_rendore(p) ;p := t.rrenjanumri(p) ;
end {MAIN}.
5
3 8
2 6
7
4
Krahasojme 7 me 5; meqenese 7 eshte mee madhe se 5 shqyrtojme birin e djathte te 5
77 eshte me e vogel se 8 prandajshqyrtojme birin e majte te 8
77 eshte me e madhe se 6 por 6 nuk ka bir tedjathte prandaj shto 7 si bir te djathte te 6
5
3 8
2 64
7
Shtimi ne nje pemete kerkimit binar
Nje efekt anesor i metodes se zakonshme te shtimit ne nje peme te kerkimit binary (BST), sipas implementimit ne proceduren e meparshme, eshte se elementet e shtuar me vone tentojne te jene me larg nga rrenja dhe prandaj duhet me shume kohe per ti gjetur ata ne krahasim me elementet e shtuar para tyre. Nese te gjithe elementet kane te njejtat gjasa per te qene kandidate te nje kerkimi atehere ky fakt nuk eshte i rendesishem, por nese jemi ne rastet e disa modeleve te perdorimit komun ku elementet e shtuar me vone tentohen te kerkohen me shpesh se ata me te hershem (nga kendveshtrimi i shtimit ne peme) atehere kemi te bejme me nje problem jo te vogel.
Nje skeme alternative per shtimin, skeme e cila adreson
edhe problemin e siperpermendur, eshte skema e shtimit nga rrenja. Sipas ketij algoritmi, nyja e re vendoset gjithmone ne rrenje te pemes. Duke ndjekur nje seri shtimesh te tilla nyjet e futura me vone kane tendence te jene me afer rrenjes se nyjet e tjera.
Si nje perpjekje te pare per implementimin e kesaj ideje, ne mund te perpiqemi ta bejme nyjen e re si rrenje te pemes dhe ta kthejme rrenjen e vjeter si nje nga bijte e saj.
Per fat te keq, ky perafrim apo ndonje tjeter i ngjashem me te, nuk do te funksionoje sepse nuk ka garanci qe nyjet ne pemen ekzistuese kane te gjitha vlera me te medha apo me te vogla se nyja e re.
Nje perafrim qe funksionon eshte kryerja e nje shtimi konvencional si nje nyje gjethe sipas algoritmit tashme te pershkruar te shtimit dhe pastaj kryerja e nje serie rrotullimesh per ta levizur nyjen e re drejt rrenjes.
Y
X c
a b
X
Ya
b c
Një rrotullim ështënjë transformim ithjeshtë i njëpeme binare qëngjan me:
ku X dhe Y përfaqësojnë nyje dhe a, b dhe c përfaqësojnë nënpemë binare arbitrare qëmund të jenë boshe. Shigjetat vertikale (mbi Y dhe X respektivisht ne figurat majtas dhedjathtas) tregojnë se pemet BST subjekte të rrotullimit mund të jenë nënpemë të një pememë të madhe. Një rrotullim e ndryshon strukturën lokale të një peme të kërkimit binar pandryshuar renditjen e saj sipas bredhjes ndërrendore.
Rrotullimet kanë vetitë e mëposhtme:Rrotullimet ndryshojnë strukturën e një peme binare. Në veçanti, rrotullimet mundet që
shpesh, në varësi të formës së pemës, të përdoren për të ndryshuar lartësinë e një pjesetë një peme binare.
Rrotullimet ndryshojnë strukturën lokale të një peme binare. Çdo rrotullim i dhënëndikon vetëm mbi nyjen e rrotulluar dhe bijtë e saj të menjëhershëm. Paraardhësit enyjes dhe bijtë e bijve të saj ngelin të pandryshuar.
Rrotullimet nuk e ndryshojnë renditjen e një peme binare. Në qoftë se një pemë binareështë një pemë e kërkimit binar para një rrotullimi atëherë ajo është një pemë e kërkimitbinar pas rrotullimit. Kështu, ne mund ti përdorim të sigurtë rrotullimet për të rirregulluarstrukturën e një peme BST pa u shqetësuar se mund të prishim renditjen e saj.
4
2
31
5
4
2
3
1
5
Rrotullim djathtas mbi 4
3 nga bir idjathte i 2behet bir imajte i 4;
4 behet biri djathte i 2
4
2
31
5
4
2
3
1
5
Rrotullim majtas mbi 2
3 nga bir imajte i 4behet bir idajthte i 2;
2 behet biri majte i 4
5
3 6
2 4
5
4 6
3
2
1 1
4
3 5
2 6
1 4
3
5
2
6
1
Rrotullimmajtas tek
3
Rrotullimdjathtas tek
5
Rrotullimmajtas tek
1
Shtimi ne BST nga rrenja Rregulli i pergjithshem ndjek modelin e treguar
ne prezantim. Neqoftese ne zbritem majtas nga nje nyje x gjate kerkimit per shtim ne kryejme nje rrotullim djathtas mbi x. Neqoftese zbritem djathtas atehere rrotullojme majtas.
Implementimi i algoritmit bazohet ne memorizimin e nyjeve te bredhura gjate kerkimit te nje pike futjeje dhe me tej ne kryerjen e rrotullimeve ne rend te kundert me bredhjen fillestare.
5
3 6
2 4
1Rrotullim
majtas tek 35
4 6
3
2
1
Shtimi ne rrenje ne nje peme te kerkimit binar
Tentojme ta shnderrojme nyjen esaposhtuar 4 ne rrenje te pemes
5
4 6
3
2
1
Shtimi ne rrenje ne nje peme te kerkimit binar
Tentojme ta shnderrojme nyjen esaposhtuar 4 ne rrenje te pemes
4
3 5
2 6
1Rrotullim
djathtas tek 5
Shtimi ne rrenje ne nje peme te kerkimit binar
Tentojme ta shnderrojme nyjen esaposhtuar 4 ne rrenje te pemes
4
3 5
2 6
1 Rrotullimmajtas tek 1
4
3
5
2
6
1
function shtim_BST_rrenja (var t : tabele_peme; elm : tip_elementi) : peme;
{shton elementet ne nje peme te tipit BST - metoda e shtimit nga rrenja}
varugjet : boolean;k : integer;p, q : peme;pa : array [1 . . max_lartesi_BST] of peme;da : array [1 . . max_lartesi_BST] of integer;
beginpa[1] := t.rrenja;p := t.rrenja;da[1] := 1 ;k := 2 ;ugjet := false;
while ((p <> nil) and not(ugjet)) doif p^.element = elm then
ugjet := trueelsebegin
{shqyrto rastin k>max_lartesi_BST}pa[k] := p;if p^.element > elm then
da[k] := 1else
da[k] := 2;p := p^.lidhje[da[k]];k := k + 1;
end;
if not(ugjet) thenbegin
new (p);p^.element := elm;p^.lidhje[1] := nil;p^.lidhje[2] := nil;pa[k-1]^.lidhje[da[k-1]] := p ;{shqyrto rastin pema boshe pra t.rrenja=nil}t.numri := t.numri +1 ;while k > 2 dobegin
q := pa[k-1];q^.lidhje[da[k-1]] := p^.lidhje[3-da[k-1]] ;p^.lidhje[3-da[k-1]] := q ;pa[k-2]^.lidhje[da[k-2]] := p;k:=k-1;
end;t.rrenja := p ;
end; shtim_BST_rrenja := p
end {shtim_BST_rrenja};
function gjej (t : tabele_peme; var p, q : peme ; var d : integer ; elm : tip_elementi) : boolean ;
{gjen vendndodhjen e nyjes se pemes me vlere elm ne pemen t duke ruajtur ne p}{shenjuesin mbi kete nyje peme (ose nil nese ajo nuk ekziston), ne q prindin e p (ose } {nil nese prindi nuk ekziston) dhe ne d kahun e birit (1 nese eshte bir i majte dhe/ose} {2 nese eshte bir i djathte)}var
ugjet : boolean;begin
ugjet := false;p := t.rrenja;q := nil ;while (not(ugjet) and (p <> nil)) doif p^.element = elm then
ugjet := trueelsebegin
if p^.element > elm thend := 1
elsed := 2;
q := p;p := p^.lidhje[d]
end ;gjej := ugjet
end {gjej};