Seite 1 von 1

KeyTree - Schlüsselwörter mit Daten

Verfasst: 03.07.2008 15:35
von Josef Sniatecki
Ich habe mal ein Template geproggt, mit dem man Schlüsselwörter
mit angehängten Daten verwalten kann.

Vorteil:
Hier werden nicht die Schlüsselwörter + Daten in eine Liste abgespeichert,
sondern in einen Datenbaum. Damit ist die schnelligkeit des Zugriffes
nur von der Länge eines Schlüsselwortes abhängig und nicht von der
Anzahl der Schlüsselwörter.

Nachteil:
Für jeden neuen Buchstabe in einer Ebene werden (26 + 2) * Long Bytes
benötigt. Bei 100 Wörtern kann das ein bisschen viel werden.

Hier ist der Code + Beispiel:

Code: Alles auswählen

;/-----------------------------------------------------------------\
;|  *** KeyTree - template ***                                     |
;|    Created by Josef Sniatecki 2008.                             |
;\-----------------------------------------------------------------/



;/------------------------------------------\
;| Structures                               |
;\------------------------------------------/

Structure KeyTree
  *Mem     ;Memory
  CharAm.l ;CharacterAmount
  *A.KeyTree
  *B.KeyTree
  *C.KeyTree
  *D.KeyTree
  *E.KeyTree
  *F.KeyTree
  *G.KeyTree
  *H.KeyTree
  *I.KeyTree
  *J.KeyTree
  *K.KeyTree
  *L.KeyTree
  *M.KeyTree
  *N.KeyTree
  *O.KeyTree
  *P.KeyTree
  *Q.KeyTree
  *R.KeyTree
  *S.KeyTree
  *T.KeyTree
  *U.KeyTree
  *V.KeyTree
  *W.KeyTree
  *X.KeyTree
  *Y.KeyTree
  *Z.KeyTree
EndStructure



;/------------------------------------------\
;| Functions                                |
;\------------------------------------------/

Procedure.l KeyTree()
  ProcedureReturn AllocateMemory(SizeOf(KeyTree))
EndProcedure
Procedure.l KeyTreeKey(*KeyTree.KeyTree,Key.s,*Mem)
  ;KeyTreeKey(Key,Memory)
  ;{
  ;  Fügt ein neues Schlüsselwort[Key] mit angegebenen
  ;  Daten[Mem] in ein KeyTree ein.
  ;}
  
  Protected *Char.Character ;Character
  Protected *CKeyTree.KeyTree     ;CurrentKeyTree
  
  *Char=@Key
  *CKeyTree=*KeyTree
  While *Char\C<>0
    If PeekL(*CKeyTree+8+(*Char\C-65)*SizeOf(Long))=0 ;Buchstabe noch nicht im KeyTree vorhanden...
      *CKeyTree\CharAm+1
      PokeL(*CKeyTree+8+(*Char\C-65)*SizeOf(Long),AllocateMemory(SizeOf(KeyTree)))
    EndIf
    *CKeyTree=PeekL(*CKeyTree+8+(*Char\C-65)*SizeOf(Long))
    *Char+1
  Wend
  
  If *CKeyTree\Mem=0
    *CKeyTree\Mem=*Mem
    ProcedureReturn *CKeyTree
  Else
    CompilerIf #PB_Compiler_Debugger
      Debug "KeyTreeKey()-error: "+Key+" is already in the KeyTree."
      Beep_(250,250)
      End
    CompilerElse
      ProcedureReturn #False
    CompilerEndIf
  EndIf
EndProcedure
Procedure.l KeyTree_Mem(*KeyTree.KeyTree,Key.s)
  ;KeyTree_Memory(KeyTree,Key)
  ;{
  ;  Gibt die Datei zurück, die dem
  ;  Schlüsselwort[Key] zugewiesen wurde.
  ;}
  
  Protected *Char.Character ;Character
  Protected *CKeyTree.KeyTree     ;CurrentKeyTree
  
  *Char=@Key
  *CKeyTree=*KeyTree
  While *Char\C<>0
    If PeekL(*CKeyTree+8+(*Char\C-65)*SizeOf(Long))
      *CKeyTree=PeekL(*CKeyTree+8+(*Char\C-65)*SizeOf(Long))
    Else
      CompilerIf #PB_Compiler_Debugger
        Debug "KeyTree_Mem()-error: "+Key+" is not in the KeyTree."
        Beep_(250,250)
        End
      CompilerElse
        ProcedureReturn #False
      CompilerEndIf
    EndIf
    *Char+1
  Wend
  
  ProcedureReturn *CKeyTree\Mem
EndProcedure
Procedure.l DelKeyTreeKey(*KeyTree.KeyTree,Key.s,DelMem.b=#True)
  ;DeleteKeyTreeKey(KeyTree,Key,DeleteMemory=#True)
  ;{
  ;  Löscht das Schlüsselwort[Key] aus
  ;  dem KeyTree. Wenn [DelMem] auf 1 gesetzt ist, so
  ;  werden auch die zugewiesenen Daten gelöscht.
  ;}
  
  Protected *Char.Character ;Character
  Protected *CKeyTree.KeyTree     ;CurrentKeyTree
  Protected *NKeyTree.KeyTree     ;NextKeyTree
  Protected *RetMem         ;ReturnMemory
  
  *Char=@Key
  *CKeyTree=*KeyTree
  While *Char\C<>0
    If PeekL(*CKeyTree+8+(*Char\C-65)*SizeOf(Long))
      *NKeyTree=PeekL(*CKeyTree+8+(*Char\C-65)*SizeOf(Long))
      If *NKeyTree\CharAm=1
        PokeL(*CKeyTree+8+(*Char\C-65)*SizeOf(Long),0)
        *CKeyTree\CharAm-1
        If *CKeyTree\CharAm=0 And *CKeyTree<>*KeyTree
          If FreeMemory(*CKeyTree)=#False
            ProcedureReturn #False
          EndIf
        EndIf
      EndIf
      *CKeyTree=*NKeyTree
    Else
      CompilerIf #PB_Compiler_Debugger
        Debug "DelKeyTreeKey()-error: "+Key+" is not in the KeyTree."
        Beep_(250,250)
        End
      CompilerElse
        ProcedureReturn #False
      CompilerEndIf
    EndIf
    *Char+1
  Wend
  
  If DelMem=#True
    If DelMem
      If FreeMemory(*CKeyTree\Mem)=#False
        ProcedureReturn #False
      EndIf
    EndIf
  EndIf
  
  If *CKeyTree\CharAm=1
    If DelMem=#False
      *RetMem=*CKeyTree\Mem
    EndIf
    If FreeMemory(*CKeyTree)
      ProcedureReturn *RetMem
    Else
      ProcedureReturn #False
    EndIf
  Else
    *CKeyTree\CharAm-1
    *RetMem=*CKeyTree\Mem
    *CKeyTree\Mem=0
    ProcedureReturn *RetMem
  EndIf
EndProcedure



;/------------------------------------------\
;| Examples                                 |
;\------------------------------------------/

Global *MyKeyTree.KeyTree=KeyTree()     ;Erstellt ein neues KeyTree.
KeyTreeKey(*MyKeyTree,"MYNAME",?MyName) ;Fügt ein Schlüsselwort mit der Datei "?MyName" ein.
KeyTreeKey(*MyKeyTree,"SOURCE",?Source)
KeyTreeKey(*MyKeyTree,"OS",?OS)

Debug "MYNAME : "       +PeekS(KeyTree_Mem(*MyKeyTree,"MYNAME")) ;Ließt ein String aus
Debug "SOURCE : "       +PeekS(KeyTree_Mem(*MyKeyTree,"SOURCE")) ;der Datei des Schlüsselwortes.
Debug "OS : "           +PeekS(KeyTree_Mem(*MyKeyTree,"OS"))
Debug "direct SOURCE : "+PeekS(*MyKeyTree\S\O\U\R\C\E\Mem)       ;Direkter zugriff.

DelKeyTreeKey(*MyKeyTree,"SOURCE",0)          ;Löscht "SOURCE" aus dem KeyTree.
Debug PeekS(KeyTree_Mem(*MyKeyTree,"SOURCE")) ;Gibt eine Warnung. (Nur wenn Debugger an ist!)

DataSection
  MyName: Data.s "Josef Sniatecki"
  Source: Data.s "KeyTree - template"
  OS:     Data.s "Windows XP"
EndDataSection
Leider ist es nur möglich Schlüsselwörter mit Großbuchstaben zu
erstellen. Es ist auch nicht möglich irgendwelche Sonderzeichen oder
Leerzeichen zu nutzen. Auch ein Unterstrich ist nicht erlaubt.

Verfasst: 03.07.2008 17:04
von Josef Sniatecki
Ich habe den ersten Beitrag geändert. Vorher habe ich mein Template
Hash genannt. Eigentlich ist das ja falsch. Hashes stellen eine Konkurrenz
für B*-Bäume. Und mein Template basierte auf einem B*-Baum. :oops:
Hier sind mehr infos: http://de.wikipedia.org/wiki/Hashtabelle