TreeLinkedList

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

TreeLinkedList

Beitrag von NicTheQuick »

Was ist eine TreeLinkedList?

Ich habe eben noch einen kleinen Fehler in meiner TreeLinkedList gefunden. Falls also jemand meine TreeLinkedList benutzt, sollte er sich hier ein Update des Codes holen.

Es gibt auch noch ein paar neue Befehle, aber die Hilfe werde ich erst später updaten. Falls es jemand sofort wissen möchte, kann ich mich auch gleich damit beschäftigen.

///Edit:

Neues Update mit neuen Funktionen:
Siehe [c]#TLL_LastMain[/c] und [c]#TLL_FirstMain[/c]

Code: Alles auswählen

Procedure TreeLL(modus.l, *TreeLL_In)
  Enumeration 1
    #TLL_NewTreeLL    ;Erstellt eine neue TreeLinkedList mit der Structuregröße *TreeLL_in und gibt ihr Handle zurück
    #TLL_NewChild     ;Erstellt unter dem aktuellen Element eine neue Childliste oder springt zum aktuellen Child des aktuellen Elementes
    
    #TLL_Add          ;Erstellt ein neues Element nach dem aktuellen oder in der neuen Childliste
    #TLL_Insert       ;Erstellt ein neues Element vor dem aktuellen
    #TLL_Delete       ;Löscht das aktuelle Element und seine Childs, falls vorhanden
    #TLL_AllDelete    ;Löscht alle Elemente
    
    #TLL_FreeTreeLL   ;Löscht die TreeLL und gibt den Speicher wieder frei
    
    #TLL_Reset        ;Resetet die aktuelle Liste, nicht die ganze
    #TLL_ResetAll     ;Resetet jede einzelne Liste
    #TLL_First        ;Springt zum ersten Element in der aktuellen Liste
    #TLL_Last         ;Springt zum letzten Element in der aktuellen Liste
    #TLL_LastMain     ;Springt zum letzten Element in der gesamten Liste
    #TLL_FirstMain    ;Springt zum ersten Element in der ersten Ebene
    
    #TLL_Prev         ;Springt zu dem Element vor dem aktuellen
    #TLL_Next         ;Springt zu dem Element nach dem aktuellen oder zum ersten, wenn die Liste resetet wurde
    #TLL_NextEx       ;Springt zum nächsten Element oder
    #TLL_Child        ;Springt zum aktuellen Child des aktuellen Elementes oder vor die Childliste
    #TLL_Parent       ;Springt zum Parent des aktuellen Elementes
    
    #TLL_GetPointer   ;Gibt den Pointer zum aktuellen Element zurück
    
    #TLL_IsPrev       ;Gibt 0 zurück, wenn kein Element vor dem aktuellen existiert, sonst Pointer zum vorherigen Element
    #TLL_IsNext       ;Gibt 0 zurück, wenn kein Element nach dem aktuellen existiert, sonst Pointer zum folgenden Element
    #TLL_IsChild      ;Gibt 0 zurück, wenn das aktuelle Element kein Child hat, sonst Pointer zum Child
    #TLL_IsParent     ;Gibt 0 zurück, wenn das aktuelle Element kein Parent hat, sonst Pointer zum Parent
    
    #TLL_CountChilds  ;Zählt die Childs des aktuellen Elements
    #TLL_CountList    ;Zählt die Elemente der aktuellen Ebene
    #TLL_CountElements;Zählt die Elemente der gesamten Liste
    #TLL_CountColumn  ;Zählt die Rekursion eines Childs
    
    #TLL_SaveTreeLL
    #TLL_LoadTreeLL
    
    #TLL_ChangeElement
  EndEnumeration
  Structure TreeLinkedListElement
    *pNext.TreeLinkedListElement
    *pPrev.TreeLinkedListElement
    *pParent.TreeLinkedListElement
    *pChild.TreeLinkedListElement
    *pChildLast.TreeLinkedListElement
    *pAktChild.TreeLinkedListElement
  EndStructure
  Structure TreeLinkedList
    *pAktElement.TreeLinkedListElement
    *pFirstElement.TreeLinkedListElement
    *pLastElement.TreeLinkedListElement
    ElementSize.l
    Status.l
  EndStructure
  Structure TreeLinkedListAllTypes
    StructureUnion
      b.b
      w.w
      l.l
      f.f
      s.s
    EndStructureUnion
  EndStructure

  ;{ Init
  Protected *New.TreeLinkedListElement, *TreeLL.TreeLinkedList
  Protected TreeLLSize.l, Count.l, OK.l, AktElementSize.l, *z.BYTE, *AllTypes.TreeLinkedListAllTypes, Struc.s, TmpS.s
  ;}
  
  If modus = #TLL_NewTreeLL       ;{ Reserviert Speicher für eine neue TreeLL und gibt das Handle zurück
    If *TreeLL_In
      *TreeLL = AllocateMemory(SizeOf(TreeLinkedList))
      *TreeLL\ElementSize = *TreeLL_In
      *TreeLL\Status = 0
      ProcedureReturn *TreeLL
    EndIf
    ProcedureReturn 0
  EndIf;}
  
  If modus = #TLL_LoadTreeLL      ;{ Läd eine TreeLL und gibt das Handle zurück
    *TreeLL = TreeLL(#TLL_NewTreeLL, ReadLong())
    Struc = ""
    Count = 0
    Repeat
      OK = ReadByte() & $FF
      If OK : Struc = Struc + Chr(OK) : EndIf
    Until OK = 0
    Repeat
      OK = ReadByte()
      Select OK
        Case 0
          *AllTypes = TreeLL(#TLL_Add, *TreeLL)
        Case 1
          TreeLL(#TLL_NewChild, *TreeLL)
        Case 2
          TreeLL(#TLL_Parent, *TreeLL)
      EndSelect
      
      If OK = 0
        *z = @Struc
        While *z\b
          Select *z\b
            Case 'b'
              *AllTypes\b = ReadByte()
              *AllTypes + 1
            Case 'w'
              *AllTypes\w = ReadWord()
              *AllTypes + 2
            Case 'l'
              *AllTypes\l = ReadLong()
              *AllTypes + 4
            Case 'f'
              *AllTypes\f = ReadFloat()
              *AllTypes + 4
            Case 's'
              Count = ReadLong()
              *AllTypes\s = Space(Count)
              ReadData(*AllTypes\l, Count)
              *AllTypes + 4
          EndSelect
          *z + 1
        Wend
      EndIf
    Until OK >= 3
    *AllTypes = 0
    If OK > 3 : ProcedureReturn 0 : EndIf
    ProcedureReturn *TreeLL
  EndIf;}
  
  ;{ PastInit
  *TreeLL = *TreeLL_In
  If *TreeLL                  ;Überprüft das Handle auf Gültigkeit
    If *TreeLL\ElementSize = 0
      ProcedureReturn 0
    EndIf
  Else
    ProcedureReturn 0
  EndIf
  
  TreeLLSize = SizeOf(TreeLinkedListElement)
  AktElementSize = TreeLLSize + *TreeLL\ElementSize;}
  
  If *TreeLL\Status = #TLL_SaveTreeLL   ;{ Speichert die gesamte TreeLL in eine geöffnete Datei
    WriteLong(*TreeLL\ElementSize)
    WriteString(PeekS(Modus))
    WriteByte(0)
    
    If *TreeLL\pFirstElement
      *New = *TreeLL\pFirstElement
      Repeat
        WriteByte(0)
        *z = Modus
        *AllTypes = *New + TreeLLSize
        While *z\b
          Select *z\b
            Case 'b'
              WriteByte(*AllTypes\b)
              *AllTypes + 1
            Case 'w'
              WriteWord(*AllTypes\w)
              *AllTypes + 2
            Case 'l'
              WriteLong(*AllTypes\l)
              *AllTypes + 4
            Case 'f'
              WriteFloat(*AllTypes\f)
              *AllTypes + 4
            Case 's'
              WriteLong(Len(*AllTypes\s))
              WriteString(*AllTypes\s)
              *AllTypes + 4
          EndSelect
          *z + 1
        Wend
        
        If *New\pChild
          *New = *New\pChild
          WriteByte(1)
        Else
          While *New\pNext = 0 And *New\pParent
            *New = *New\pParent
            WriteByte(2)
          Wend
          *New = *New\pNext
        EndIf
      Until *New = 0
      WriteByte(3)
      *TreeLL\Status = 0
      ProcedureReturn 1
    EndIf
    *TreeLL\Status = 0
    ProcedureReturn 0
  EndIf;}
  
  If *TreeLL\Status = #TLL_ChangeElement ;{ Springt zum Element an einer bestimmten Adresse
    If Modus
      *TreeLL\pAktElement = Modus - TreeLLSize
    EndIf
    *TreeLL\Status = 0
    ProcedureReturn 1
  EndIf ;}
  
  ;{ Select
  Select modus
    Case #TLL_GetPointer    ;{ Gibt den Pointer zum aktuellen Element zurück
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pAktChild = -1
          ProcedureReturn -1
        Else
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        EndIf
      ElseIf *TreeLL\pFirstElement
        ProcedureReturn -1
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_Add           ;{ Füge ein neues Element hinter dem Aktuellen ein
      *New = AllocateMemory(AktElementSize)
      
      If *TreeLL\pAktElement And *TreeLL\pAktElement\pAktChild <> -1    ;Wenn Element aktiv ist
        If *TreeLL\pAktElement\pChild = -1        ;Wenn ein Child erstellt werden soll
          *TreeLL\pAktElement\pChild = *New
          *TreeLL\pAktElement\pChildLast
          *New\pParent = *TreeLL\pAktElement
        Else
          *New\pNext = *TreeLL\pAktElement\pNext
          *New\pPrev = *TreeLL\pAktElement
          *TreeLL\pAktElement\pNext = *New
          If *New\pNext
            *New\pNext\pPrev = *New
          EndIf
          *New\pParent = *TreeLL\pAktElement\pParent
          If *New\pPrev = 0           ;Wenn 1. Pos hat
            If *New\pParent
              *New\pParent\pChild = *New
            Else
              *TreeLL\pFirstElement = *New
            EndIf
          EndIf
          If *New\pNext = 0           ;Wenn letzte Pos hat
            If *New\pParent
              *New\pParent\pChildLast = *New
            Else
              *TreeLL\pLastElement = *New
            EndIf
          EndIf
        EndIf
      ElseIf *TreeLL\pFirstElement       ;Wenn resettet wurde
        *New\pNext = *TreeLL\pFirstElement
        *TreeLL\pFirstElement\pPrev = *New
        *TreeLL\pFirstElement = *New
      Else                      ;Wenn noch kein Element vorhanden war
        *TreeLL\pFirstElement = *New
        *TreeLL\pLastElement = *New
      EndIf
      *TreeLL\pAktElement = *New
      ProcedureReturn *New + TreeLLSize;}
    
    Case #TLL_Insert        ;{ Füge ein neues Element ein
      *New = AllocateMemory(AktElementSize)
      If *TreeLL\pAktElement And *TreeLL\pAktElement\pAktChild <> -1    ;Wenn Element aktiv ist
        If *TreeLL\pAktElement\pChild = -1        ;Wenn ein Child erstellt werden soll
          *TreeLL\pAktElement\pChild = *New
          *TreeLL\pAktElement\pChildLast
          *New\pParent = *TreeLL\pAktElement
        Else
          *New\pNext = *TreeLL\pAktElement
          *New\pPrev = *TreeLL\pAktElement\pPrev
          *TreeLL\pAktElement\pPrev = *New
          If *New\pPrev
            *New\pPrev\pNext = *New
          EndIf
          *New\pParent = *TreeLL\pAktElement\pParent
          If *New\pPrev = 0           ;Wenn 1. Pos hat
            If *New\pParent
              *New\pParent\pChild = *New
            Else
              *TreeLL\pFirstElement = *New
            EndIf
          EndIf
          If *New\pNext = 0           ;Wenn letzte Pos hat
            If *New\pParent
              *New\pParent\pChildLast = *New
            Else
              *TreeLL\pLastElement = *New
            EndIf
          EndIf
        EndIf
      ElseIf *TreeLL\pFirstElement   ;Wenn resettet wurde
        *New\pNext = *TreeLL\pFirstElement
        *TreeLL\pFirstElement\pPrev = *New
        *TreeLL\pFirstElement = *New
      Else                      ;Wenn noch kein Element vorhanden war
        *TreeLL\pFirstElement = *New
        *TreeLL\pLastElement = *New
      EndIf
      *TreeLL\pAktElement = *New
      ProcedureReturn *New + TreeLLSize;}
    
    Case #TLL_Next          ;{ Springe zum nächsten Element
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pAktChild = -1
          *TreeLL\pAktElement\pAktChild = 0
          *TreeLL\pAktElement = *TreeLL\pAktElement\pChild
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        ElseIf *TreeLL\pAktElement\pNext
          *TreeLL\pAktElement = *TreeLL\pAktElement\pNext
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        EndIf
      ElseIf *TreeLL\pFirstElement
        *TreeLL\pAktElement = *TreeLL\pFirstElement
        ProcedureReturn *TreeLL\pAktElement + TreeLLSize
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_Reset         ;{ Resete die aktuelle Rekursion
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pParent
          *TreeLL\pAktElement\pParent\pAktChild = -1
          *TreeLL\pAktElement = *TreeLL\pAktElement\pParent
          ProcedureReturn 1
        Else
          *TreeLL\pAktElement = 0
          ProcedureReturn 1
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_ResetAll      ;{ Resetet jede Liste
      If *TreeLL\pFirstElement
        *New = *TreeLL\pFirstElement
        c = 0
        Repeat
          If *New\pChild
            *New\pAktChild = 0
            *New = *New\pChild
          Else
            While *New\pNext = 0 And *New\pParent
              *New = *New\pParent
            Wend
            *New = *New\pNext
          EndIf
          c + 1
        Until *New = 0
        *TreeLL\pAktElement = 0
        ProcedureReturn 1
      EndIf
      ProcedureReturn 0
      ;}
    
    Case #TLL_Delete        ;{ Löscht das aktuelle Element samt seinen Childs
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pChild
          *New = *TreeLL\pAktElement\pChild
          Repeat
            If *New\pChild
              *New = *New\pChild
            Else
              While *New\pNext = 0 And *New\pParent <> *TreeLL\pAktElement
                *New\pParent\pChild = *New
                *New = *New\pParent
                FreeMemory(*New\pChild)
              Wend
              If *New\pNext
                *New = *New\pNext
                FreeMemory(*New\pPrev)
              Else
                FreeMemory(*New)
                *New = 0
              EndIf
            EndIf
          Until *New = 0
        EndIf
        ;{ Hier gehts weiter
        *New = *TreeLL\pAktElement
        If *TreeLL\pAktElement\pPrev
          *TreeLL\pAktElement\pPrev\pNext = *TreeLL\pAktElement\pNext
        Else
          If *TreeLL\pAktElement\pParent
            *TreeLL\pAktElement\pParent\pChild = *TreeLL\pAktElement\pNext
          Else
            *TreeLL\pFirstElement = *TreeLL\pAktElement\pNext
          EndIf
        EndIf
        If *TreeLL\pAktElement\pNext
          *TreeLL\pAktElement\pNext\pPrev = *TreeLL\pAktElement\pPrev
        Else
          If *TreeLL\pAktElement\pParent
            *TreeLL\pAktElement\pParent\pChildLast = *TreeLL\pAktElement\pPrev
          Else
            *TreeLL\pLastElement = *TreeLL\pAktElement\pPrev
          EndIf
        EndIf
        If *TreeLL\pAktElement\pParent
          If *TreeLL\pAktElement\pParent\pAktChild = *TreeLL\pAktElement
            *TreeLL\pAktElement\pParent\pAktChild = 0
          EndIf
        EndIf
        
        If *TreeLL\pAktElement\pPrev = 0
          If *TreeLL\pAktElement\pParent
            *TreeLL\pAktElement = *TreeLL\pAktElement\pParent
            *TreeLL\pAktElement\pAktChild = -1
          Else
            *TreeLL\pAktElement = 0
          EndIf
        Else
          *TreeLL\pAktElement = *TreeLL\pAktElement\pPrev
        EndIf
        FreeMemory(*New)
        ProcedureReturn 1
      EndIf;}
      ProcedureReturn 0;}
    
    Case #TLL_AllDelete     ;{ Löscht alle Elemente
      If *TreeLL\pFirstElement
        *New = *TreeLL\pFirstElement
        Repeat
          If *New\pChild
            *New = *New\pChild
          Else
            While *New\pNext = 0 And *New\pParent
              *New\pParent\pChild = *New
              *New = *New\pParent
              FreeMemory(*New\pChild)
            Wend
            If *New\pNext
              *New = *New\pNext
              FreeMemory(*New\pPrev)
            Else
              FreeMemory(*New)
              *New = 0
            EndIf
          EndIf
        Until *New = 0
        *TreeLL\pAktElement = 0
        *TreeLL\pFirstElement = 0
        *TreeLL\pLastElement = 0
        ProcedureReturn 1
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_NewChild      ;{ Erstelle das Grundgerüst für ein neues Child oder springe zum Child
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pChild = 0
          *TreeLL\pAktElement\pChild = -1
          ProcedureReturn -1
        ElseIf *TreeLL\pAktElement\pChild <> -1
          If *TreeLL\pAktElement\pAktChild = 0 Or *TreeLL\pAktElement\pAktChild = -1
            *TreeLL\pAktElement\pAktChild = -1
            ProcedureReturn -1
          Else
            *TreeLL\pAktElement = *TreeLL\pAktElement\pAktChild
          EndIf
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_Child         ;{ Springe zum aktuellen Child
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pChild And *TreeLL\pAktElement\pChild <> -1
          If *TreeLL\pAktElement\pAktChild = 0 Or *TreeLL\pAktElement\pAktChild = -1
            *TreeLL\pAktElement\pAktChild = -1
            ProcedureReturn -1
          Else
            *TreeLL\pAktElement = *TreeLL\pAktElement\pAktChild
            ProcedureReturn *TreeLL\pAktElement + TreeLLSize
          EndIf
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_Parent        ;{ Springe zum Parent
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pAktChild = -1
          *TreeLL\pAktElement\pAktChild = 0
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        ElseIf *TreeLL\pAktElement\pChild = -1
          *TreeLL\pAktElement\pChild = 0
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        ElseIf *TreeLL\pAktElement\pParent
          *TreeLL\pAktElement\pParent\pAktChild = *TreeLL\pAktElement
          *TreeLL\pAktElement = *TreeLL\pAktElement\pParent
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_IsParent      ;{ Hat dieses Element ein Parent?
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pParent And *TreeLL\pAktElement\pAktChild <> -1
          ProcedureReturn *TreeLL\pAktElement\pParent + TreeLLSize
        Else
          ProcedureReturn 0
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_Last          ;{ Springe zum letzten Element
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pAktChild = -1
          *TreeLL\pAktElement\pAktChild = 0
          *TreeLL\pAktElement = *TreeLL\pAktElement\pChild
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        ElseIf *TreeLL\pAktElement\pParent
          *TreeLL\pAktElement = *TreeLL\pAktElement\pParent\pChildLast
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        Else
          *TreeLL\pAktElement = *TreeLL\pLastElement
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_LastMain      ;{ Springe zum letzten Element in der gesamten Liste
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pAktChild = -1
          *TreeLL\pAktElement\pAktChild = 0
        EndIf
        *New = *TreeLL\pLastElement
        While *New\pChildLast
          *New = *New\pChildLast
        Wend
        *TreeLL\pAktElement = *New
        ProcedureReturn *TreeLL\pAktElement + TreeLLSize
      EndIf
    
    Case #TLL_First         ;{ Springe zum ersten Element
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pAktChild = -1
          *TreeLL\pAktElement\pAktChild = 0
          *TreeLL\pAktElement = *TreeLL\pAktElement\pChild
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        ElseIf *TreeLL\pAktElement\pParent
          *TreeLL\pAktElement = *TreeLL\pAktElement\pParent\pChild
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        Else
          *TreeLL\pAktElement = *TreeLL\pFirstElement
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_FirstMain     ;{ Springe zum ersten Element der ersten Ebene
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pAktChild = -1
          *TreeLL\pAktElement\pAktChild = 0
          *TreeLL\pAktElement = *TreeLL\pFirstElement
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        Else
          *TreeLL\pAktElement = *TreeLL\pFirstElement
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_IsNext        ;{ Folgt diesem Element noch eins?
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pAktChild = -1
          ProcedureReturn *TreeLL\pAktElement\pChild + TreeLLSize
        ElseIf *TreeLL\pAktElement\pNext
          ProcedureReturn *TreeLL\pAktElement\pNext + TreeLLSize
        Else
          ProcedureReturn 0
        EndIf
      ElseIf *TreeLL\pFirstElement
        ProcedureReturn *TreeLL\pFirstElement + TreeLLSize
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_NextEx        ;{ Springe zum nächsten Element oder zum Parent und zu dessen Nachfolger
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pAktChild = -1
          *TreeLL\pAktElement\pAktChild = 0
          *TreeLL\pAktElement = *TreeLL\pAktElement\pChild
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        ElseIf *TreeLL\pAktElement\pChild
          *TreeLL\pAktElement = *TreeLL\pAktElement\pChild
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        ElseIf *TreeLL\pAktElement\pNext
          *TreeLL\pAktElement = *TreeLL\pAktElement\pNext
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        Else
          While *TreeLL\pAktElement\pParent And *TreeLL\pAktElement\pNext = 0
            *TreeLL\pAktElement = *TreeLL\pAktElement\pParent
          Wend
          If *TreeLL\pAktElement\pNext
            *TreeLL\pAktElement = *TreeLL\pAktElement\pNext
            ProcedureReturn *TreeLL\pAktElement + TreeLLSize
          Else
            ProcedureReturn 0
          EndIf
        EndIf
      ElseIf *TreeLL\pFirstElement
        *TreeLL\pAktElement = *TreeLL\pFirstElement
        ProcedureReturn *TreeLL\pAktElement + TreeLLSize
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_IsChild       ;{ Hat dieses Element ein Child?
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pChild And *TreeLL\pAktElement\pAktChild <> -1
          ProcedureReturn *TreeLL\pAktElement\pChild + TreeLLSize
        Else
          ProcedureReturn 0
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_Prev          ;{ Springe zum vorherigen Element
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pPrev And *TreeLL\pAktElement\pAktChild <> -1
          *TreeLL\pAktElement = *TreeLL\pAktElement\pPrev
          ProcedureReturn *TreeLL\pAktElement + TreeLLSize
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_IsPrev        ;{ Geht diesem Element eins voraus?
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pPrev And *TreeLL\pAktElement\pAktChild <> -1
          ProcedureReturn *TreeLL\pAktElement\pPrev + TreeLLSize
        Else
          ProcedureReturn 0
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_CountChilds   ;{ Gibt die Anzahl der Childs zurück
      If *TreeLL\pAktElement
        If *TreeLL\pAktElement\pChild
          *New = *TreeLL\pAktElement\pChild
          Count = 1
          While *New\pNext
            *New = *New\pNext
            Count + 1
          Wend
          ProcedureReturn Count
        Else
          ProcedureReturn 0
        EndIf
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_CountList     ;{ Gibt die Anzahl der Elemente in dieser Rekursion zurück
      If *TreeLL\pFirstElement
        *New = *TreeLL\pFirstElement
      Else
        ProcedureReturn 0
      EndIf
      
      Count = 1
      While *New\pNext
        *New = *New\pNext
        Count + 1
      Wend
      ProcedureReturn Count;}
    
    Case #TLL_CountElements ;{ Gibt die Anzahl aller Elemente zurück
      If *TreeLL\pFirstElement
        *New = *TreeLL\pFirstElement
        Count = 0
        Repeat
          If *New\pChild
            *New = *New\pChild
            Count + 1
          Else
            While *New\pNext = 0 And *New\pParent
              *New = *New\pParent
            Wend
            *New = *New\pNext
            Count + 1
          EndIf
        Until *New = 0
        ProcedureReturn Count
      EndIf
      ProcedureReturn 0;}
    
    Case #TLL_CountColumn   ;{ Gibt die Anzahl der Rekursion des Elements zurück
      If *TreeLL\pAktElement
        Count = 0
        If *TreeLL\pAktElement\pAktChild = -1
          *New = *TreeLL\pAktElement\pAktChild
        Else
          *New = *TreeLL\pAktElement
        EndIf
        While *New\pParent
          Count + 1
          *New = *New\pParent
        Wend
        ProcedureReturn Count
      EndIf
      ProcedureReturn 0;}

    Case #TLL_SaveTreeLL    ;{ Speichert die gesamte TreeLL in eine geöffnete Datei (s.o.)
      *TreeLL\Status = #TLL_SaveTreeLL
      ProcedureReturn 1;}
    
    Case #TLL_ChangeElement ;{ Springt zum Element an einer bestimmten Adresse
      *TreeLL\Status = #TLL_ChangeElement
      ProcedureReturn 1;}
    
    Case #TLL_FreeTreeLL    ;{ Löscht die TreeLL und gibt den Speicher wieder frei
      If TreeLL(#TLL_AllDelete, *TreeLL)
        If FreeMemory(*TreeLL)
          ProcedureReturn 1
        EndIf
      EndIf
      ProcedureReturn 0
    
    Default
      ProcedureReturn 0;}
  EndSelect;}
EndProcedure
Zuletzt geändert von NicTheQuick am 05.09.2005 16:30, insgesamt 2-mal geändert.
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: TreeLinkedList

Beitrag von Kiffi »

Hai Nic,

vielen Dank für Deine TreeLinkedList! :allright:

Im alten Forum hattest Du mal angedacht, die TLL direkt an ein TreeGadget
zu koppeln, um den Umgang mit dem TreeGadget ein wenig zu vereinfachen
(siehe TreeGadget: Inhalt laden und speichern).

Hast Du diesbezüglich schon was unternommen?

Danke & Grüße ... Kiffi
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Noch nicht. Bin aber gerade dabei.
Dauert hoffentlich nicht lange.
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

> Bin aber gerade dabei.

Sehr gute Nachricht! :allright:

Gespannt wartend ... Kiffi
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

///Edit:
Neue Procedures für die TreeGadget-TreeLinkedList-Kopplung. Funktioniert nur mit der aktuellsten TreeLL.

Code: Alles auswählen

Procedure OnErrorMessage()
  Protected Fehler.s
  Fehler = "Fehler in Modul '" + GetErrorModuleName() + "' an Adresse " + RSet(Hex(GetErrorAddress()), 4, "0") + " in Zeile " + Str(GetErrorLineNR()) + ":" + Chr(13) + GetErrorDescription()
  MessageRequester("Fehler Nr. " + Str(GetErrorNumber()), Fehler)
  SetClipboardText("Fehler Nr. " + Str(GetErrorNumber()) + Chr(13) + Fehler)
  End
EndProcedure
OnErrorGosub(@OnErrorMessage())

XIncludeFile "TreeLinkedList.pb"

;{ TreeGadget with TreeLinkedList

Structure TGwTLL
  ID.l
  *LL
EndStructure

Procedure TLL_SeekElement(*LL, Position)
  If Position <= -1
    TreeLL(#TLL_FirstMain, *LL)
  Else
    TreeLL(#TLL_ResetAll, *LL)
    While TreeLL(#TLL_NextEx, *LL) And Position
      Position - 1
    Wend
  EndIf
EndProcedure

Procedure.l TLL_TreeGadget(GadgetID.l, X.l, Y.l, Breite.l, Hoehe.l, Flags.l)
  Protected *TGwTLL.TGwTLL
  *TGwTLL = AllocateMemory(SizeOf(TGwTLL))
  If *TGwTLL
    *TGwTLL\ID = TreeGadget(Gadget, X, Y, Breite, Hoehe, Flags)
    If Gadget <> #PB_Any : *TGwTLL\ID = Gadget : EndIf
    *TGwTLL\LL = TreeLL(#TLL_NewTreeLL, 4)
    ProcedureReturn *TGwTLL
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_GetGadgetID(*TGwTLL.TGwTLL)
  If *TGwTLL
    ProcedureReturn *TGwTLL\ID
  EndIf
EndProcedure

Procedure.l TLL_AddGadgetItem(*TGwTLL.TGwTLL, Position.l, Text.s, ImageID)
  Protected a.l, *Text.STRING
  If *TGwTLL
    AddGadgetItem(*TGwTLL\ID, Position, Text)
    If Position <= -1
      TreeLL(#TLL_LastMain, *TGwTLL\LL)
    Else
      TLL_SeekElement(*TGwTLL\LL, Position)
    EndIf
    *Text = TreeLL(#TLL_Add, *TGwTLL\LL)
    If *Text
      *Text\s = Text
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_RemoveGadgetItem(*TGwTLL.TGwTLL, Position.l)
  If *TGwTLL And Position >= 0
    RemoveGadgetItem(*TGwTLL\ID, Position)
    TLL_SeekElement(*TGwTLL\LL, Position)
    TreeLL(#TLL_Delete, *TGwTLL\LL)
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_ClearGadgetItemList(*TGwTLL.TGwTLL)
  If *TGwTLL
    ClearGadgetItemList(*TGwTLL\ID)
    TreeLL(#TLL_AllDelete, *TGwTLL\LL)
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_CountGadgetItems(*TGwTLL.TGwTLL)
  Protected Count.l
  If *TGwTLL
    Count = CountGadgetItems(*TGwTLL\ID)
    ProcedureReturn Count
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_GetGadgetItemState(*TGwTLL.TGwTLL, Position.l)
  If *TGwTLL
    ProcedureReturn GetGadgetItemState(*TGwTLL\ID, Position)
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_SetGadgetItemState(*TGwTLL.TGwTLL, Position.l, State.l)
  If *TGwTLL
    ProcedureReturn SetGadgetItemState(*TGwTLL\ID, Position, State)
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.s TLL_GetGadgetItemText(*TGwTLL.TGwTLL, Position.l)
  If *TGwTLL
    ProcedureReturn GetGadgetItemText(*TGwTLL\ID, Position, 0)
  EndIf
EndProcedure

Procedure.l TLL_SetGadgetItemText(*TGwTLL.TGwTLL, Position.l, Text.s)
  Protected *Text.STRING
  If *TGwTLL And Position >= 0
    SetGadgetItemText(*TGwTLL\ID, Position, Text, 0)
    TLL_SeekElement(*TGwTLL, Position)
    *Text = TreeLL(#TLL_GetPointer, *TGwTLL)
    If *Text
      *Text\s = Text
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_GetGadgetState(*TGwTLL.TGwTLL)
  If *TGwTLL
    ProcedureReturn GetGadgetState(*TGwTLL\ID)
  EndIf
EndProcedure

Procedure.l TLL_SetGadgetState(*TGwTLL.TGwTLL, State.l)
  If *TGwTLL
    ProcedureReturn SetGadgetState(*TGwTLL\ID, State.l)
  EndIf
EndProcedure

Procedure.s TLL_GetGadgetText(*TGwTLL.TGwTLL)
  If *TGwTLL
    ProcedureReturn GetGadgetText(*TGwTLL\ID)
  EndIf
EndProcedure

Procedure.s TLL_GetTLLText(*TGwTLL.TGwTLL)
  Protected Position.l, *Text.STRING
  If *TGwTLL
    Position = GetGadgetState(*TGwTLL\ID)
    If Position >= 0
      TLL_SeekElement(*TGwTLL\LL, Position)
      *Text = TreeLL(#TLL_GetPointer, *TGwTLL\LL)
      If *Text
        ProcedureReturn *Text\s
      EndIf
    EndIf
  EndIf
  ProcedureReturn ""
EndProcedure

Procedure.l TLL_SetGadgetText(*TGwTLL.TGwTLL, Text.s)
  Protected Position.l, *Text.STRING
  If *TGwTLL
    Position = GetGadgetState(*TGwTLL\ID)
    If Position >= 0
      SetGadgetText(*TGwTLL\ID, Text)
      TLL_SeekElement(*TGwTLL\LL, Position)
      *Text = TreeLL(#TLL_GetPointer, *TGwTLL\LL)
      *Text\s = Text
    EndIf
  EndIf
EndProcedure

Procedure.l TLL_OpenTreeGadgetNode(*TGwTLL.TGwTLL, Position.l)
  If *TGwTLL
    If Position <= -1
      OpenTreeGadgetNode(*TGwTLL\ID)
      TreeLL(#TLL_LastMain, *TGwTLL\LL)
      TreeLL(#TLL_NewChild, *TGwTLL\LL)
    Else
      OpenTreeGadgetNode(*TGwTLL\ID, Position)
      TLL_SeekElement(*TGwTLL\LL, Position)
      TreeLL(#TLL_NewChild, *TGwTLL\LL)
    EndIf
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_CloseTreeGadgetNode(*TGwTLL.TGwTLL, Position.l)
  If *TGwTLL
    If Position <= -1
      CloseTreeGadgetNode(*TGwTLL\ID)
    Else
      CloseTreeGadgetNode(*TGwTLL\ID, Position)
    EndIf
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_CountTreeGadgetNodeItems(*TGwTLL.TGwTLL, Position.l)
  If *TGwTLL
    ProcedureReturn CountTreeGadgetNodeItems(*TGwTLL\ID, Position.l)
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_GadgetItemID(*TGwTLL.TGwTLL, Position.l)
  If *TGwTLL
    ProcedureReturn GadgetItemID(*TGwTLL\ID, Position)
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.l TLL_TreeGadgetItemNumber(*TGwTLL.TGwTLL, Position.l)
  If *TGwTLL
    ProcedureReturn TreeGadgetItemNumber(*TGwTLL\ID, Position)
  EndIf
  ProcedureReturn #False
EndProcedure

;}

Procedure.s RandomWord(Length.l)
  Protected As.s, Bs.s, Wort.s, a.l, modus.l, b.l, TmpS.s
  modus = 1
  As = "aeiouy"
  Bs = "bcdfghjklmnpqrstvwxz"
  Wort = ""
  Repeat
    Select modus
      Case 1
        b = 1
        TmpS = As
      Case 2
        b = Random(2)
        TmpS = Bs
    EndSelect
    
    For a = 1 To b
      Wort = Wort + Mid(TmpS, Random(Len(TmpS) - 1) + 1, 1)
    Next
    modus ! 3
  Until Len(Wort) >= Length
  ProcedureReturn Left(Wort, Length)
EndProcedure

Procedure RandomTree(TGwTLL.l, Length.l)
  Protected Child.l, a.l
  
  TLL_ClearGadgetItemList(TGwTLL)
  While Length
    Select Random(2 * Length / (11 - Child))
      Case 0: If Child < 10 : TLL_OpenTreeGadgetNode(TGwTLL, -1) : Child + 1 : EndIf
      Case 1: If Child > 0 : TLL_CloseTreeGadgetNode(TGwTLL, -1) : Child - 1 : EndIf
    EndSelect
    TLL_AddGadgetItem(TGwTLL, -1, RSet(Str(a), 3, "0") + " [" + Str(Child) + "] " + RandomWord(Random(20)), 0)
    a + 1
    Length - 1
  Wend
  While Child
    TLL_CloseTreeGadgetNode(TGwTLL, -1)
    Child - 1
  Wend
EndProcedure

Procedure ShowAll(*TGwTLL.TGwTLL)
  Protected *Text.STRING
  TreeLL(#TLL_ResetAll, *TGwTLL\LL)
  While TreeLL(#TLL_NextEx, *TGwTLL\LL)
    *Text = TreeLL(#TLL_GetPointer, *TGwTLL\LL)
    If *Text
      Debug *Text\s
      b = Val(Left(*Text\s, 3))
    EndIf
  Wend
EndProcedure


If OpenWindow(0, 0, 0, 300, 500, #PB_Window_ScreenCentered | #PB_Window_SystemMenu, "TGwTLL-Test")
  If CreateGadgetList(WindowID(0))
    TLL.l = TLL_TreeGadget(#PB_Any, 0, 0, 300, 480, #PB_Tree_AlwaysShowSelection)
    But1.l = ButtonGadget(#PB_Any, 0, 480, 150, 20, "Random")
    But2.l = ButtonGadget(#PB_Any, 150, 480, 150, 20, "Alle")
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_EventCloseWindow
          Break
        Case #PB_EventGadget
          Select EventGadgetID()
            Case TLL_GetGadgetID(TLL)
              Select EventType()
                Case #PB_EventType_LeftDoubleClick
                  Debug "TreeGadget: " + TLL_GetGadgetText(TLL)
                  Debug "TreeLL: " + TLL_GetTLLText(TLL)
              EndSelect
            Case But1
              RandomTree(TLL, 100)
            Case But2
              ShowAll(TLL)
          EndSelect
      EndSelect
    ForEver
  EndIf
  CloseWindow(0)
EndIf
Entspricht das deinen Erwartungen bezüglich des Anwendungsstils? Natürlich fehlt hier jetzt noch das wichtigste: Die Lade- und Speicherfunktion. Aber ich muss mal eben für eine Stunde weg hier. Bis später also.
Zuletzt geändert von NicTheQuick am 30.09.2004 19:38, insgesamt 1-mal geändert.
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

> Entspricht das deinen Erwartungen bezüglich des Anwendungsstils?

bin gerade dabei, das ganze zu testen.

Du hast einen kleinen Typo in Deiner TLL:

Code: Alles auswählen


390: *trell\pAktElement\pParent\pChildLast = *trell\pAktElement\pPrev
Erstmal vielen Dank für Deine Hilfe & Grüße ... Kiffi
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Hm... Also irgendwas läuft da noch total schief.

Würde es dir auch reichen, ein TreeGadget einfach nur mit einer TreeLinkedList synchronisieren zu lassen? Also du benutzt ein TreeGadget wie du es immer machst und dann kannst du mit einer Funktion das komplette TreeGadget in einer TreeLinkedList speichern und auch andersrum? Natürlich werden dann auch die CheckBoxes gespeichert, falls welche da sind.

///Edit:

So, ich habe den Fehler entdeckt und durch ein TreeLL-Update behoben. Siehe Post oben.
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

öhm, ich habs jetzt erst entdeckt, testen konnt ich des noch nciht und ich weiß auch nicth, wann ich dazu komme, aber ich hätte mal eine algemeine geschwindigkeitsfrage ... da ich mir das ganze noch nicht anschauen konnte würd gerne schon vorher mal wissen, ob das schneller ist, als wenn man selber das ganze in Linklisten machen würde, natürlich dann ohne Baumstruckture ;-) oder obs gleich schnell ist, weil vorteile hätte das ganze ja :allright:

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Benutzeravatar
crossroads
Beiträge: 244
Registriert: 29.08.2004 05:41
Wohnort: Rhine Main Area

Undocumented feature

Beitrag von crossroads »

[hochschieb]
Ich experimentiere gerade mit der TreeLL und vermisse schmerzlich einen Befehl, um zu einem beliebigen Element zu springen - doch halt:

Undocumented feature found!

Code: Alles auswählen

#TLL_ChangeElement ;{ Springt zum Element an einer bestimmten Adresse 
Syntax:

Code: Alles auswählen

restore = *Tree.struct
; kreuz und quer durch die TreeLL springen ...
TreeLL(#TLL_ChangeElement, hdl)
TreeLL(restore, hdl)
*Tree.struct = TreeLL(#TLL_GetPointer, hdl)
Hat mir sehr weitergeholfen :wink:

@Nic:
Vielleicht könntest Du mal die Doku überarbeiten und anschließend Code/Doku/Example als Update an André weitergeben ... :allright:
[/hochschieb]
Man soll die Tür aufmachen, bevor man durchgeht ...
Antworten