Algorytmy i struktury danych/Wyszukiwanie: Różnice pomiędzy wersjami
Linia 61: | Linia 61: | ||
'''end'''; | '''end'''; | ||
Wstawianie do drzewa jest bardzo zbliżone do wyszukiwania, musimy przejść po drzewie (rozpoczynająć w korzeniu) | Wstawianie do drzewa jest bardzo zbliżone do wyszukiwania, musimy przejść po drzewie | ||
aby odnaleźć wolne miejsce w którym możemy dodać nową wartość. | (rozpoczynająć w korzeniu) aby odnaleźć wolne miejsce w którym możemy dodać nową wartość. | ||
'''procedure''' Dodaj(wezel, klucz) | '''procedure''' Dodaj(wezel, klucz) | ||
Linia 71: | Linia 71: | ||
'''else''' | '''else''' | ||
Dodaj(wezel.lewePoddrzewo, klucz) | Dodaj(wezel.lewePoddrzewo, klucz) | ||
''' else if (klucz >= wezel.klucz) '''then''' | '''else if (klucz >= wezel.klucz) '''then''' | ||
'''if''' wezel.prawePoddrzewo=nil '''then''' | '''if''' wezel.prawePoddrzewo=nil '''then''' | ||
utwórz nowy węzeł z wartością ''klucz'' | utwórz nowy węzeł z wartością ''klucz'' | ||
Linia 79: | Linia 79: | ||
'''end'''; | '''end'''; | ||
Możemu również usuwać wartości z drzewa, niestety ta operacja jest bardziej skomplikowana. | |||
* usuwanie | '''procedure''' Usun(wezel, klucz) | ||
'''if''' (klucz < wezel.klucz) '''then''' | |||
Usun(wezel.lewePoddrzewo, klucz) | |||
'''else if (klucz > wezel.klucz) '''then''' | |||
Usun(wezel.prawePoddrzewo, klucz) | |||
'''else''' '''begin''' { klucz = wezel.klucz | |||
jeśli '''wezel''' jest liściem, to: | |||
{ usuń '''wezel''' z drzewa } | |||
UsunProstyPrzypadek(wezel) | |||
wpp. | |||
* jeśli wezel.lewePoddrzewo <> nil, to: | |||
niech $x$ oznacza skrajnie prawy węzeł w poddrzewie wezel.lewePoddrzewo | |||
wezel.klucz:=x.klucz; | |||
UsunProstyPrzypadek(x); | |||
* wpp. analogiczne postępowanie dla wezel.prawPoddrzewo | |||
(jednak poszukujemy węzła na skrajnie lewej ścieżce) | |||
'''end''' | |||
Procedura ''UsunProstyPrzypadek'' oznacza usuwanie z drzewa węzła, który | |||
ma co najwyżej jednego syna. | |||
'''procedure''' UsunProstyPrzypadek(wezel) | |||
poddrzewo:=nil; | |||
ojciec:=wezel.ojciec; | |||
'''if''' (wezel.lewePoddrzewo) '''then''' | |||
poddrzewo:=wezel.lewePoddrzewo; | |||
'''else''' | |||
poddrzewo:=wezel.prawePoddrzewo; | |||
'''if''' (ojeciec=nil) '''then''' | |||
korzen:=poddrzewo; | |||
'''else''' '''if''' ojciec.lewePoddrzewo=wezel '''then''' { węzeł jest lewym synem } | |||
ojciec.lewePoddrzewo:=podrzewo; | |||
'''else''' { węzeł jest prawym synem } | |||
ojciec.prawePoddrzewo:=podrzewo; | |||
== Haszowanie == | == Haszowanie == | ||
TODO | TODO |
Wersja z 14:25, 4 sie 2006
Wyszukiwanie
W niniejszym wykładzie opiszemy podstawowe techniki dotyczące wyszukiwania.
Zajmiemy się również prostymi strukturami słownikowymi, które oprócz
wyszukiwania, umożliwiają dodawanie i usuwanie elementów.
Wyszukiwanie liniowe
TODO
function Szukaj(x, A[1..n]) begin for i:=1 to n do if A[i]=x return i; return brak poszukiwanego elementu; end
Wyszukiwanie binarne
TODO
function WyszukiwanieBinarne(x, A[1..n]) { zakładamy, że tablica A, jest uporządkowana rosnąco } begin l:=1;r:=n; while (l<=r) do begin m:=(l+r) div 2; if (A[m]<x) then l:=m+1 else if (A[m]>x) then r:=m-1 else return m; { ponieważ A[m]=x } end; return brak poszukiwanego elementu; end;
Drzewa poszukiwań binarnych
Drzewa poszukiwań binarnych, to zwykłe drzewa binarne, których klucze spełniają następujące własności:
Dla dowolnego węzła x:
- wszystkie klucze w lewym poddrzewie węzła x, mają wartości mniejsze niż klucz węzła x,
- wszystkie klucze w lewym poddrzewie węzła x, mają wartości większe lub równe niż klucz węzła x.
TODO -- przykładowe drzewo
Dodatkowe wymaganie dotyczące kluczy, umożliwia nam efektywne wszyskiwanie elementów w drzewie.
function Szukaj(wezel, klucz) if (wezel==nil) return BRAK ELEMENTU if (wezel.klucz=klucz) then return ELEMENT ISTNIEJE else if (klucz < wezel.klucz) then return Szukaj(wezel.lewePoddrzewo, klucz) else if (klucz > wezel.klucz) then return Szukaj(wezel.prawPoddrzewo, klucz) end;
Wstawianie do drzewa jest bardzo zbliżone do wyszukiwania, musimy przejść po drzewie (rozpoczynająć w korzeniu) aby odnaleźć wolne miejsce w którym możemy dodać nową wartość.
procedure Dodaj(wezel, klucz) if (klucz < wezel.klucz) then if wezel.lewePoddrzewo=nil then utwórz nowy węzeł z wartością klucz wskaźnik do nowego węzła zapisujemy w wezel.lewePoddrzewo else Dodaj(wezel.lewePoddrzewo, klucz) else if (klucz >= wezel.klucz) then if wezel.prawePoddrzewo=nil then utwórz nowy węzeł z wartością klucz wskaźnik do nowego węzła zapisujemy w wezel.prawePoddrzewo else Dodaj(wezel.prawePoddrzewo, klucz) end;
Możemu również usuwać wartości z drzewa, niestety ta operacja jest bardziej skomplikowana.
procedure Usun(wezel, klucz) if (klucz < wezel.klucz) then Usun(wezel.lewePoddrzewo, klucz) else if (klucz > wezel.klucz) then Usun(wezel.prawePoddrzewo, klucz) else begin { klucz = wezel.klucz jeśli wezel jest liściem, to: { usuń wezel z drzewa } UsunProstyPrzypadek(wezel) wpp. * jeśli wezel.lewePoddrzewo <> nil, to: niech $x$ oznacza skrajnie prawy węzeł w poddrzewie wezel.lewePoddrzewo wezel.klucz:=x.klucz; UsunProstyPrzypadek(x); * wpp. analogiczne postępowanie dla wezel.prawPoddrzewo (jednak poszukujemy węzła na skrajnie lewej ścieżce) end
Procedura UsunProstyPrzypadek oznacza usuwanie z drzewa węzła, który ma co najwyżej jednego syna.
procedure UsunProstyPrzypadek(wezel) poddrzewo:=nil; ojciec:=wezel.ojciec; if (wezel.lewePoddrzewo) then poddrzewo:=wezel.lewePoddrzewo; else poddrzewo:=wezel.prawePoddrzewo; if (ojeciec=nil) then korzen:=poddrzewo; else if ojciec.lewePoddrzewo=wezel then { węzeł jest lewym synem } ojciec.lewePoddrzewo:=podrzewo; else { węzeł jest prawym synem } ojciec.prawePoddrzewo:=podrzewo;
Haszowanie
TODO