Just tried and after smoking help file here is the result. Maybe not too good & optimized (I'm using PB < 1 week and don't know too much), but if you like try it.
Also would be nice to get some improvements [it is always nice]
// thanx DontTalkToMe for explaining my mistake with pointers, now pointers replaced to a simple array indexes
Code: Select all
; Binary Tree implementation using array and structures
; Copyright (C) 2015 Lunasole
; * A horrible "Redim() and pointers bug" explained by DontTalkToMe :3
;
; This program is Free software: you can redistribute it And/Or modify
; it under the terms of the GNU General Public License As published by
; the Free Software Foundation, either version 3 of the License, Or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY Or FITNESS For A PARTICULAR PURPOSE. See the
; GNU General Public License For more details.
;
; You should have received a copy of the GNU General Public License
; along With this program. If Not, see <http://www.gnu.org/licenses/>.
EnableExplicit
Structure TreeNode
Right.i ; pointer to right follower (array element)
Left.i ; pointer to left follower
Data.s ; stored data string
EndStructure
Global Dim TreeNodes.TreeNode (511) ; "backend" array. dont set initial size to zero, must be at least 1
Global TreeNenum.i = 0 ; current amount of array elements used
Global TreeNgrow.i = 2048 ; a step to increase array by: lower value causes more often ReDim usage and slowing tree. don't set it to <= 0
Global TMP.TreeNode ; to store a new node data while processing
; this function receives array index and starts/continues from that node
; if new node data is > than actual node data, it goes to right, else left. If data is equal, false is returned and recursion stops
Procedure.b TreeRecurse (Index.i)
Define CMP.i = CompareMemoryString(@TMP\Data, @TreeNodes(Index)\Data, #PB_String_CaseSensitive)
If CMP > 0
If Not (TreeNodes(Index)\Right = 0) ; if there is follower
ProcedureReturn TreeRecurse(TreeNodes(Index)\Right) ; ... continue recursive search
Else
TreeNodes (TreeNenum) = TMP ; save new node into array
TreeNodes(Index)\Right = TreeNenum ; set new node as follower of actual node (right vector)
;Debug "+right"
TreeNenum = TreeNenum+1 : If TreeNenum > ArraySize(TreeNodes()) : ReDim TreeNodes.TreeNode (TreeNenum + TreeNgrow) : EndIf ; enlarge your Array [if needed]
ProcedureReturn #True
EndIf
ElseIf CMP < 0 ; all the same, but left vector
If Not (TreeNodes(Index)\Left = 0)
ProcedureReturn TreeRecurse(TreeNodes(Index)\Left)
Else
TreeNodes (TreeNenum) = TMP
TreeNodes(Index)\Left = TreeNenum
;Debug "+left"
TreeNenum = TreeNenum+1 : If TreeNenum > ArraySize(TreeNodes()) : ReDim TreeNodes.TreeNode (TreeNenum + TreeNgrow) : EndIf
ProcedureReturn #True
EndIf
EndIf
EndProcedure
; add new node to a tree. if success, return true. if node with the same data exists, function will return false
; in total, all this is made to find and delete duplicate strings [the fastest way I know], but may be modified and extended for many other things
Procedure.b TreeInsert (iStr.s)
Tmp\Left = 0 ; clr temp node
Tmp\Right = 0
Tmp\Data = iStr
If TreeNenum = 0 ; set up Parent node
TreeNodes(TreeNenum) = TMP
TreeNenum = TreeNenum + 1
ProcedureReturn #True
Else ; proceed tree starting from Parent node
ProcedureReturn TreeRecurse(0)
EndIf
EndProcedure
; erase tree
Procedure TreeClear ()
Dim TreeNodes.TreeNode (1)
TreeNenum = 0
EndProcedure
;usage
Debug TreeInsert("2")
Debug TreeInsert("1")
Debug TreeInsert("4")
Debug TreeInsert("1") ; duplicate, will return false
Debug TreeInsert("01")
Debug "Tree Array: " + Str(TreeNenum) + " of " + Str(ArraySize(TreeNodes()) + 1) + " filled"
TreeClear () ; discard tree