Temat: Drzewa trie

Transkrypt

Temat: Drzewa trie
Temat: Drzewa trie
1. Definicja drzewa trie
Drzewo trie (z ang. retrieval) to prefiksowe drzewo wielokierunkowe
słu ce do zapami tania zbioru słów nad pewnym ustalonym
alfabetem. Kluczem wyszukiwania w drzewie trie jest prefiks słowa, a
nie całe słowo. Relacj porównywania kluczy w drzewie trie jest
porz dek leksykograficzny porównywanych prefiksów.
• Danymi w drzewie trie s słowa znajduj ce si w li ciach.
• W zły wewn trzne to tablice wska ników do poddrzew trie. Na
ka dym poziomie i sprawdzamy w tablicy indeks odpowiadaj cy
i-tej literze przetwarzanego słowa. Je li wska nik na tej pozycji
jest pusty, to danego słowa nie ma w drzewie. Je li wska nik jest
niepusty, to kontynuujemy przetwarzanie a do osi gni cia li cia
zawieraj cego szukane słowo.
• W ka dym w le u ywamy dodatkowo specjalnego znaku, nie
wyst puj cego w adnym słowie (w przykładach jest to znak
„#”). Podczas poszukiwania na przykład słowa „ARE” po
przetworzeniu znaków „A”, „R”, „E” znajdziemy si na
czwartym poziomie drzewa trie, w w le, którego synami s
li cie „ARE” i „AREA”. Poniewa przetworzyli my ju
wszystkie litery klucza „ARE”, sprawdzamy wska nik
odpowiadaj cy ko cowi słowa, czyli „#”, a skoro jest on
niepusty, wnioskujemy, e słowo nale y do struktury.
1
Przykład 1
Drzewo trie dla przykładowego zbioru słów nad alfabetem : A, E, I,
P, R
# A E I
# A
E I
# A
P R
E
# A
I P R
E
E
R
I
E
A
# A E
A
R
A
A
R
E
A
R
E
A
I
E I
P
R
E
I
R
E
P R
# A E
# A
E
E
R
A
E
R
E
I P R
E
R
I
E
P R
I
P R
I
P
A
I
R
E
# A E
# A E I
P
E
A
R
P
E
E
R
I
P R
P R
P
E
R
# A E
P
I
E
R
# A
I
E
P R
I P R
R
E
P
R
E
A
R
• Wysoko drzewa trie wyznacza najdłu szy wspólny prefiks, a
dokładnie wysoko ta wynosi najdłu szy wspólny prefiks +1.
Dla wi kszo ci słów w j zyku angielskim operacja
wyszukiwania w drzewie trie ko czyłaby po odwiedzeniu kilku
w złów, zapewne 5-7. Byłoby to prawd tak dla 10000 słów, jak
i dla 100000. Odpowiednie wywa one drzewo poszukiwa
binarnych (np. drzewo AVL) dla 10000 słów miałoby wysoko
lg 10000 = 14. Poniewa wi kszo
słów le ałaby na
najni szych poziomach tego drzewa, podczas wyszukiwania
rednio odwiedzałoby si 13 w złów. Jest to dwukrotnie wi cej
ni dla drzewa trie.
2
• W drzewie poszukiwa binarnych jest porównywany cały
szukany klucz z kluczem w bie cym w le, podczas gdy w
drzewie trie w porównywaniu bior udział tylko pojedyncze
znaki.
2. Operacja wstawiania słowa do drzewa trie
Ze wzgl du na fakt, e drzewo trie zawiera dwa rodzaje w złów,
wstawianie do niego klucza jest nieco bardziej skomplikowane ni
wstawianie klucza do drzewa poszukiwa binarnych.
Przykład 2
Drzewo trie przed wstawieniem słowa „REP”
# A E I
# A
E I
P R
# A
E I
P R
# A E
P R
I
P R
# A E
I
P R
R
E
A
R
# A
E
I P R
E
E
R
I
E
A
# A E
A
R
A
A
R
E
A
R
E
A
I
P
R
E
I
R
E
# A
E
E
R
A
E
R
E
I P R
E
R
I
E
I
P
A
I
R
E
# A E I
P
E
A
R
P
E
E
R
P R
P
I
E
R
P
E
R
3
Zakładamy, e wstawiamy do słownika wył cznie słowa niepuste.
Wywołanie algorytmu wstawiania powinno by poprzedzone
sprawdzeniem, czy słowa wstawianego nie ma ju w drzewie.
Przykład 3
Drzewo trie po wstawieniu słowa „REP”
# A E I
# A
E I
P R
# A
E I
P R
# A E
P R
I
P R
# A E
I
P R
# A E
I
P R
p
# A
E
I P R
E
E
R
I
E
A
# A E
A
R
A
A
R
E
A
R
E
A
I
P
R
E
I
R
E
# A
E
E
R
A
E
R
E
I P R
E
R
I
E
I
P
A
I
R
E
# A E I
P
E
A
R
P
E
E
R
P R
P
E
R
P
I
E
R
# A
E
I P R
R
E
P
R
E
A
R
K_L
4
K
TrieInsert (K)
// K - słowo wstawiane, r – korze drzewa trie,
i = 0;
// ptrs – tablica wska ników na w zły potomne w w złach
p = r;
// wewn trznych
wstawiony=0;
while (!wstawiony)
{
if (K [i] == ‘ \ 0 ‘ )
{
utwórz li L zawieraj cy K;
p->ptrs[#]=L; wstawiony=1;
}
else if (p->ptrs[K[i]] == NULL)
{
utwórz li L zawieraj cy K;
p->ptrs[K[i]]=L; wstawiony=1;
}
else if (w zeł p->ptrs[K[i]] jest li ciem)
{
K _ L = klucz w li ciu p->ptrs[K[i]];
zwolnij pami dla li cia p-> ptrs[K[i]];
while (K[i] == K _ L[i])
{
utwórz w zeł wewn trzny N;
p->ptrs[K[i]]=N;
p =N;
i++;
};
utwórz li L zawieraj cy K;
p->ptrs[K[i]]=L;
if (K [i] == ‘ \ 0 ‘)
{
utwórz li L zawieraj cy K;
p->ptrs[0]=L; wstawiony=1;
}
else {
utwórz li L zawieraj cy K _ L;
p->ptrs[K_L[i]]=L;
wstawiony=1;
}
}
else p = p->ptrs[K[i++]];
}
5
• Dla drzew trie kolejno wstawiania kluczy jest nieistotna,
decyduje ona natomiast o kształcie drzew poszukiwa
binarnych.
3. Drzewa trie optymalne pami ciowo
Główny problem zwi zany z drzewami trie to wielko pami ci,
której potrzebuj . Znacz ca jej cz
jest w zasadzie marnowana.
Wiele w złów mo e zawiera zaledwie kilka niepustych wska ników,
a pozostałe, mimo, e s puste, musz zajmowa pami .
a) Drzewo trie, w którego li ciach znajduj si tylko
nie przetworzone sufiksy
Przykład 4
Drzewo trie, w którego li ciach zapami tane s tylko sufiksy słów
# A E I P R
# A E I P R
# A E I P R
# A E I P R
\0
# A E I P R
\0
\0
R
I
E
R
E
# A E I P R
# A E I P R
\0
\0
E
A
I
# A E I P R
# A E I P R
R
R
P
E
R
# A E I P R
E
R
# A E I P R
R
\0
\0
6
b) Drzewo trie z dynamicznymi w złami wewn trznymi
Jednym ze sposobów zmniejszenia rozmiaru w zła jest zapisywanie
tylko tych wska ników, które s faktycznie u ywane. Jeden w zeł
drzewa trie odpowiada teraz li cie.
Przykład 5
Drzewo trie z dynamiczn struktur w zła
A
#
A
R /
A
E
E / E
E
R
I
E
A
R
A
#
A
R
A
E
E
I
R
E
A /
I
I
A
R /
E
E
R
A
E
R
E
A
R
E
A
P
P
R /
I / I I
P R
A E
E
R
I
E
R /
A
P
E
A
R
E
E
P
E
E
R
I /
R /
P
E
R
P
I
E
R
E /
A
R
E
A
R
P /
R
E
P
c) Drzewo trie typu a tergo
Inn metod redukcji wymaga pami ciowych jest zmiana sposobu
sprawdzania słów. Do drzewa trie a tergo (z łac.: od tyłu) s
wstawiane słowa odwrócone. Drzewo trie a tergo reprezentuj ce takie
słowa, jak „logged”, „loggerhead”, „loggia”, „logging”, miałoby li cie
na trzecim poziomie, a nie na siódmym, jak w zwykłym drzewie trie.
7
Dla pewnych cz sto spotykanych ko cówek, jak angielskie „tion”,
„ism”, czy „ics”, problem pojawiłby si znowu.
4. Kompresja drzewa trie
Przykład 6
Sposoby kompresji drzewa trie
# A E
P1
# A E
P3
I
P
I
P
R
P2
R
# A E
P6
P4 P5
I
P
P7
R
(a)
(a)
TrieNodes
CellArray
P1
1 2 3
P3 P2 P4 P5 P6
P7
(b)
TrieNodes
CellArray
P1 P6
1 2 3
P7 P2 P3
P4 P5
(c)
8
Innym sposobem oszcz dzania pami ci jest kompresja drzewa trie. W
jednej z metod tworzy si jedn du tablice ze wszystkich tablic w
w złach wewn trznych, przeplataj c je tak, by wska niki si nie
nało yły. Pozycje pocz tkowe tych tablic s zapami tane w tablicy
pomocniczej. Na przykład trzy w zły pokazane w przykładzie 6 na
rysunku (a), zawieraj ce wska niki od p1 do p 7 do innych w złów
drzewa trie (w tym li ci), s kolejno umieszczane w jednej tablicy tak,
by nie spowodowa konfliktu. Powstaje pytanie, jak zrobi to
efektywnie ze wzgl du na czas i pami , tak by algorytm był szybki, a
powstała tablica zajmowała istotnie mniej miejsca ni wszystkie
w zły wewn trzne w sumie. W przykładzie 6 na rysunku (a) na w zły
potrzeba 3*6 = 18 komórek pami ci, a tablica zajmuje 11 komórek,
współczynnik kompresji wynosi wi c (18 - 11)/18, czyli 39%. Je li
jednak umie ci w zły w sposób pokazany na rysunku 4c, to
współczynnik ten wyniesie (18 - 10)/18, a wi c 44%.
Okazuje si , e algorytm słu cy kompresji drzewa wg sposobu (c) w
Przykładzie 6 jest wykładniczy ze wzgl du na liczb w złów i nie daje
si stosowa do du ych drzew. Inne algorytmy mog nie dawa
optymalnego współczynnika kompresji, s jednak szybsze. Jednym z
takich algorytmów jest CompressTrie ().
CompressTrie ()
// NodeNum – liczba w złów drzewa,
// CellNum – rozmiar alfabetu słów +1
// CellArray – tablica z adresami wszystkich w złów drzewa trie
wpisz warto NULL do wszystkich NodeNum*CellNum
komórek tablicy CellArray;
dla ka dego w zła node
dla ka dej pozycji j w tablicy CellArray
if (po nało eniu pól w zła node na komórki
CellArray[j], . . . , CellArray[j+CellNum-1] nie
naszły na siebie adne komórki zawieraj ce
wska niki)
{
skopiuj wska niki z node do odpowiadaj cych
im komórek, zaczynaj c od CellArray[j];
9
zapisz j w tablicy TrieNodes jako pozycj
w zła node w tablicy CellArray;
break;
}
Ten wła nie algorytm został zastosowany do drzewa trie z rysunku
(a) w przykładzie 6 w celu otrzymania tablicy na rysunku (b) tego
przykładu. Przeszukiwanie tak skompresowanego drzewa trie jest
bardzo podobne do przeszukiwania zwyczajnego drzew trie. Dost p
do w złów odbywa si jednak za po rednictwem tablicy TrieNodes.
Je li w zeł node1 jest poł czony z node2 , to trzeba odnale pozycj
node2 w tej tablicy, a nast pnie mo na si ga do pól w zła node2 w
tablicy CellArray.
Problem przy korzystaniu ze skompresowanego drzewa trie polega
na tym, e poszukiwanie mo e wywie nas na manowce. Na przykład
poszukiwanie słowa zaczynaj cego si od litery P w drzewie trie na
rysunku (a) z przykładu 6 zostałoby natychmiast przerwane, poniewa
pole wska nikowe odpowiadaj ce tej literze w korzeniu jest równe
NULL. Z kolei w skompresowanej wersji tego samego drzewa trie
(rysunek (b)) w polu odpowiadaj cym literze P znajduje si wska nik
P3. Bł dna cie ka zostałaby wykryta pó niej po napotkaniu
wska nika równego NULL lub po osi gni ciu li cia, przy porównaniu
klucza w tym li ciu szukanym.
Kolejnym sposobem kompresji jest utworzenie struktury zwanej Ctrie, b d cej bitow wersj zwykłego drzewa trie. W metodzie tej
w zły na jednym poziomie drzewa C-trie s umieszczane w kolejnych
miejscach w pami ci, a adresy pierwszych w złów na ka dym
poziomie s przechowywane w tablicy adresów. Informacja
przechowywana w konkretnych w złach pozwala na dost p do synów
tych w złów przez obliczenie przesuni cia od nich do ich synów.
10
Przykład 7
Drzewo C-trie
# AE IP R
0 0 1 1 1 1 1 0
# AE IP R
# AE IP R
0 110 0 0 0 1 0 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 4 0 0 0 1 1 0 0 6 0 00 0 1 0 0 0 8
0 01 1 0 0 0 01 0
1 0
1 01 1 1 0 0 2 1 1 I P A
1 1 I R E
0 0 0 1 1 0 0 5 ...
E E R IE EIRE
Czy li
?
# A E I
P R
pole C: ł czna liczba jedynek
w polu K we wszystkich
w złach tego samego
poziomu drzewa
poprzedzaj cych dany w zeł
Ka dy w zeł ma cztery pola: znacznik li /w zeł wewn trzny, pole
z informacj , czy to koniec słowa (pełni ce te sam funkcj co
wcze niej znak #), pole K składaj ce si z CellNum bitów
odpowiadaj cych komórkom ze znakami oraz pole C zawieraj ce
ł czn liczb jedynek we wszystkich polach K w złów na tym samym
poziomie poprzedzaj cych dany. Ta ostatnia liczba stanowi liczb
w złów na nast pnym poziomie poprzedzaj cych pierwszego syna
danego w zła.
11
W li ciach s przechowywane same klucze (albo ich sufiksy),
je eli mieszcz si w polach K i C razem. Je li nie, to klucz jest
umieszczany w osobnej tablicy, a li zawiera wska nik do jego
pozycji w tej tablicy. Do odró nienia tych dwóch przypadków słu y
znacznik ko ca słowa. Wszystkie w zły s tego samego rozmiaru.
Zakładamy, e li mo e pomie ci do trzech znaków.
Aby wyszuka klucz w strukturze C-trie, trzeba bardzo uwa nie
wylicza przesuni cia. Oto zarys algorytmu:
CTrieSearch (K)
for (i = 1, p = korze ; ; i++)
if p jest li ciem
if K jest równy kluczowi p
return sukces;
else return pora ka;
else if (K [i] == ‘ \ 0 ‘ )
if znacznik ko ca słowa jest wł czony
return sukces;
else return pora ka;
else if bit odpowiadaj cy znakowi K[i] jest zerem
return pora ka;
else
p = adres pierwszego w zła na poziomie (i+1)
+ (pole C w zła p)*(rozmiar jednego w zła)
+ (liczba jedynek w polu K w zła p na lewo od
bitu odpowiadaj cego K[i])*(rozmiar w zła);
Aby na przykład znale słowo „EERIE” w C-trie na rysunku
powy ej sprawdzamy najpierw w korzeniu bit odpowiadaj cy
pierwszej literze – „E”. Poniewa jest on równy 1, a korze nie jest
li ciem, idziemy na drugi poziom. Adres w zła do sprawdzenia na
poziomie drugim wyznaczamy, dodaj c do adresu pierwszego w zła
na tym poziomie długo jednego w zła, aby go przeskoczy . Bit tego
w zła wewn trznego odpowiadaj cy drugiej literze naszego słowa,
równie „E”, jest równy 1, idziemy wi c na poziom trzeci. Adres
w zła do sprawdzenia obliczamy, dodaj c do adresu pierwszego w zła
na poziomie trzecim rozmiar jednego w zła (pierwszego w zła na
12
poziomie trzecim). Dochodzimy teraz do li cia ze znacznikiem ko ca
słowa równym 0. Si gamy wi c do tablicy słów, aby porówna
przechowywany w niej klucz z szukanym.
Kompresja jest znaczna. Jeden w zeł pierwotnego drzewa trie o 27
dwubajtowych wska nikach zajmuje 54 bajty. Na jeden w zeł
struktury C-trie potrzeba 1 + 1 + 27 + 16 = 45 bitów, co mo na
pomie ci w 6 bajtach. Nie dostajemy tego jednak za darmo.
Algorytm wymaga umieszczania w złów jednego poziomu ciasno
obok siebie, a zapisywanie w złów po jednym na raz z u yciem
funkcji ma11oc() nie gwarantuje, e b d one znajdowa si na
s siaduj cych pozycjach, zwłaszcza w rodowisku z wieloma
u ytkownikami. W zły jednego poziomu musz zatem by tworzone
najpierw w tymczasowym pomocniczym obszarze, a dopiero potem
mo na za da przydzielenia fragmentu pami ci dostatecznie du ego,
aby pomie ci wszystkie te w zły. Problem ten pokazuje tak e, e
struktura C-trie kiepsko nadaje si do dynamicznej aktualizacji. Je li
drzewo trie jest tworzone tylko raz, to C-trie jest jego doskonale
nadaj cym si do wykorzystania wariantem. Je li natomiast potrzebna
jest cz sta aktualizacja, to t technik kompresji drzewa trie
nale ałoby wykluczy .
Przykładem zastosowania drzewa trie jest moduł sprawdzania
pisowni w edytorach tekstu.
13

Podobne dokumenty