Indexed Trie (schnelle Wortsuche)

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

Eingeproggt

Betreff: Indexed Trie (schnelle Wortsuche)

BeitragFr, Nov 18, 2011 16:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Servus,

ich hab mal n Nachmittag frei und um mal was Produktives zu machen und auch noch um den Uni-Stoff ein wenig besser verstehen zu können hab ich "Indexed Tries" umgesetzt.

Ich bin irgendwie überrascht, dass es dazu keinen Wikipedia-Artikel in deutsch gibt und in englisch finde ich auch nicht genau den, aber die grundlegende Idee geht hieraus hervor: http://en.wikipedia.org/wiki/Radix_tree

Das heißt ich muss mich doch hinsetzen und versuchen mein Werk zu erklären... also gut:
Wenn man sehr viele Wörter (Strings) hat und diese in einem Array oder auch in Types organisiert ist die Suche nach einem Wort in der Regel sehr performance-fressend da man die Liste (egal ob Array oder Type) von vorn nach hinten durchmustern muss.

Die Organisation in einer Baumstruktur liegt hier natürlich nahe - und ich habe mich für den Indexed-Tree entschieden da er am einfachsten zu implementieren ist und sehr schön schnell ist. Leider auch enormen Speicherverbrauch hat (In meinem beigelegtem Test mit 10.000 zufallsgenerierten Wörtern ~48MB RAM!)
Für die Laufzeit-Freaks unter euch: Alle Funktionen haben "konstante" Laufzeit. Da darüber in der Vorlesung schon heftig diskutiert wurde sag ich fairerweise dazu: "konstant" im Vergleich zu der Anzahl der Wörter - aber linear im Vergleich zur Wortlänge.

Möglichkeiten zur Speicheroptimierung gibt es zwar, aber darauf hab ich jetzt keine Lust. Die Sache ist eigentlich verdammt einfach aber ich befürchte ehrlich gesagt eh dass sich keiner für den Code interessiert da niemand weiß was er damit machen soll Rolling Eyes

Ein Beispiel findet man in der 2. Codebox, es demonstriert die grundlegende Verwendung ("functional") sowie die Ausführungsgeschwindigkeit ("performance"). Der letzte Teil ("comparison") ist ziemlich gepfuscht, möglicheriwese is der Geschwindigkeitsvergleich sogar falsch... aber ich dachte ich pack das noch dazu.

Wer weitere Fragen hat, der stelle sie bitte.

BlitzBasic: [AUSKLAPPEN]
;Indexed Tries

;Ascii-Set except the first 32 codes (0-31)
;Although it is possible to change these for memory-optimization inte 26 for example, please do not to this!
;You will need to modify the position-calculation too and that was not my intention.
Const alphabet_size=96

Global IT_root.router=New router

Type router
Field trie_data.trie_data[alphabet_size]
Field next_router.router[alphabet_size]
End Type

;You can modify this type to anything you need to
;(but please do not change the name)
Type trie_data
Field txt$
Field key$
End Type

;Insert a word. init with root=IT_root and i=0
;Insert the same word twice won't make sense!
Function IT_Insert(root.router,word$,i,trie_data.trie_data)
Local char=0
If i=Len(word$) Then
char=Asc(Mid(word$,i,1))-32
root\trie_data[char]=trie_data
Else
char=Asc(Mid(word$,i+1,1))-32
If root\next_router[char]=Null Then
root\next_router[char]=New router
;all end_flags are automatcally false,
;all next_router are automatically null
EndIf
IT_Insert(root\next_router[char],word$,i+1,trie_data)
EndIf
End Function

;Search a word, init with root=IT_root and i=0
Function IT_Search.trie_data(root.router,word$,i)
Local char=0
If root=Null Then Return Null
If i<Len(word$) Then
char=Asc(Mid(word$,i+1,1))-32
Return IT_Search(root\next_router[char],word$,i+1)
Else
char=Asc(Mid(word$,i,1))-32
Return root\trie_data[char]
EndIf
End Function

;Remove a word from the trie, init with root=IT_root and i=0
;use optional clean_mode to clean up empty nodes (may take longer but frees memory)
;please note that the trie_data of the removed word will NOT be deleted (because maybe you need it?)
Function IT_Delete(root.router,word$,i,clean_mode=False)
Local char=0,ok=False
If root=Null Then Return
If i<Len(word$) Then
char=Asc(Mid(word$,i+1,1))-32
IT_Delete(root\next_router[char],word$,i+1,clean_mode)
Else
char=Asc(Mid(word$,i,1))-32
root\trie_data[char]=Null
EndIf
If clean_mode Then
ok=True
For j=0 To alphabet_size
If root\trie_data[j]<>Null Or root\next_router[j]<>Null Then
ok=False
EndIf
Next
If ok Then
If root<>IT_root Then Delete root
EndIf
EndIf
End Function

;Calculates memory-usage in Bytes for the current trie
;does not consider the trie_data - this is up to you!
Function IT_GetMemory()
Local router.router
Local count=0
For router=Each router
count=count+1
Next
Return count*alphabet_size*2*4
End Function


BlitzBasic: [AUSKLAPPEN]
;-------------- TESTING

;functional

Local trie_data.trie_data=New trie_data
trie_data\txt$="This is very informative text for 'Hello'"
trie_data\key$="Hello" ;This is JUST for testing, usually NOT required

DebugLog "Insert 'Hello'"
IT_Insert(IT_root,"Hello",0,trie_data)
IT_Insert(IT_root,"Hello",0,trie_data)

DebugLog "Memory-Usage: "+IT_GetMemory()

Local result.trie_data=IT_Search(IT_root,"Hello",0)
If result=Null Then
DebugLog "No matches for 'Hello'"
Else
DebugLog "We found the following for 'Hello':"
DebugLog " "+result\txt$
EndIf

DebugLog "Delete 'Hello'"
IT_Delete(IT_root,"Hello",0,True)

DebugLog "Memory-Usage: "+IT_GetMemory()

;performance

Local count
For i=0 To 10000
trie_data.trie_data=New trie_data
count=Rand(10,30)
For j=0 To count
trie_data\txt$=trie_data\txt$+Chr(Rand(65,91))
Next
count=Rand(5,10)
For j=0 To count
trie_data\key$=trie_data\key$+Chr(Rand(65,91))
Next
Next

Local time=MilliSecs()
For trie_data=Each trie_data
IT_Insert(IT_root,trie_data\key$,0,trie_data)
Next
DebugLog "10.000 Inserts in "+(MilliSecs()-time)+"ms"

DebugLog "Memory-Usage: "+IT_GetMemory()

time=MilliSecs()
For trie_data=Each trie_data
result=IT_Search(IT_root,trie_data\key$,0)
If result=Null Then
DebugLog "There is a problem! "+trie_data\key$+" not found."
EndIf
Next
DebugLog "10.000 Searches in "+(MilliSecs()-time)+"ms"

;mode=0 ; dirty delete, doesn't free the memory
mode=1 ; clean delete
time=MilliSecs()
For trie_data=Each trie_data
IT_Delete(IT_root,trie_data\key$,0,mode)
Next
DebugLog "10.000 Deletes in "+(MilliSecs()-time)+"ms"

DebugLog "Memory-Usage: "+IT_GetMemory()

;comparison

DebugLog "Search for 10.000 words using the naive way"
;Shuffle the words to avoid linearity
Dim words$(10000)
For i=0 To 10000
count=Rand(0,10000)
trie_data=First trie_data
For j=0 To count-1
trie_data=After trie_data
Next
words$(i)=trie_data\key$
Next

time=MilliSecs()
For i=0 To 10000
For trie_data=Each trie_data
If trie_data\key$=words$(i) Then
Exit
EndIf
Next
Next
DebugLog "10.000 'naively searches' in "+(MilliSecs()-time)+"ms"

DebugLog "done"
WaitKey()
End


mfG, Christoph.
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9

ozzi789

BeitragFr, Nov 18, 2011 23:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Abend Eingeproggt

Danke für den Code, sieht spannend aus.
Werd ich mir jetzt mit ner Tasse Tee zu gemüte führen!

Mfg
Ozzi
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

BladeRunner

Moderator

BeitragSa, Nov 19, 2011 12:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Code als solches ist supi, aber bitte bitte bitte, es heisst: TREE, nicht Trie Wink
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Noobody

BeitragSa, Nov 19, 2011 12:17
Antworten mit Zitat
Benutzer-Profile anzeigen
BladeRunner hat Folgendes geschrieben:
Der Code als solches ist supi, aber bitte bitte bitte, es heisst: TREE, nicht Trie

Nicht mal Razz Siehe Wikipedia-Eintrag Trie
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun

BladeRunner

Moderator

BeitragSa, Nov 19, 2011 12:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Oha! man lernt nie aus. Danke für die Aufklärung und Entschuldigung für mein fehlerhaftes Eingreifen...
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group