Author Topic: Binary Tree Algorithm  (Read 11996 times)

0 Members and 1 Guest are viewing this topic.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Binary Tree Algorithm
« Reply #45 on: July 31, 2013, 08:11:01 AM »
That SetValueAtIndex basically rebuilds the entire tree recursively, checking if the current index is as specified by the index argument. See if you understand it better if I over-comment it:
Code - Auto/Visual Lisp: [Select]
  1. (defun Tree:SetValueAtIndex (tree index value / doSet)
  2.   (defun doSet (tree index / tmp) ;Define the helper function as a nested function so it doesn't interfere with name clashes
  3.     (cond ((or (not index) (= index 0)) (cons value (cdr tree))) ;If the index arg is nil or 0 this is the position where the value needs to go, so return it into the tree
  4.           ((atom index) ;If the index arg is an atom, then we're at the correct level and branch
  5.            (repeat index (setq tmp (cons (car tree) tmp) tree (cdr tree))) ;Fill the return with the tree's nodes preceding the index
  6.            (append (reverse tmp) (list (doSet (car tree) nil)) (cdr tree))) ;Join the preceding, new value and following nodes of the tree, and return it
  7.           ((= (length index) 1) (doSet tree (car index))) ;If the index is only 1 number, call this function with only the number, not the list
  8.           (t ;Else (index consists of 2 or more levels)
  9.            (repeat (car index) (setq tmp (cons (car tree) tmp) tree (cdr tree))) ;Fill the return with the tree's nodes preceding the index
  10.            (append (reverse tmp) (list (doSet (car tree) (cdr index))) (cdr tree))))) ;Join the preceding, new value and following nodes of the tree, and return it
  11.                                                                                       ;The new value for the node is generated recursively, by removing the highest level of the index
  12.                                                                                       ;then calling this same function with the node of the tree as if it's a tree on its own
  13.   (doSet tree index)) ;Call the helper function and return whatever it returns.
The doSet is calling itself for each level it runs through the index. Most of the work is done in the Else portion of the cond structure.
  • It copies the nodes before the current level's index argument to the returned variable
  • It then calculates the new node by calling itself with only the node at that index and the rest of the index's levels
  • Then it appends the values obtained from the previous 2 and the rest of the current portion of the tree.
I could've done it all without a nested helper function, but since the value argument never changes - it's not necessary to send for each recursion. Thus it's an attempt to make it a bit more optimal: AutoLisp copies each argument to the instance of the new function every time it's called.

The 1st option in the cond structure could actually be omitted. Since the repeat would not run, and the append would not include a nil into the result. It's only there for some optimization.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

udaaf

  • Guest
Re: Binary Tree Algorithm
« Reply #46 on: July 31, 2013, 08:50:33 PM »
@Irneb,

Once again many thanks for your explanation  :-).
I'll learn.