proc tree_set_root { treevar node } { upvar $treevar tree array set tree [list root $node $node:dad {} $node:cld {}] } proc tree_get_root { treevar } { upvar $treevar tree return $tree(root) } proc tree_isroot { treevar node } { upvar $treevar tree return [expr {([string equal $tree(root) $node])? 1 : 0}] } proc tree_get_children { treevar node } { upvar $treevar tree return $tree($node:cld) } proc tree_get_father { treevar node } { upvar $treevar tree return $tree($node:dad) } proc tree_exists { treevar node} { upvar $treevar tree return [info exists tree($node:cld)] } proc tree_add_children { treevar node children } { upvar $treevar tree foreach child $children { if { [info exists tree($child:dad)] } { tree_remove_children tree($child:dad) $child } else { set tree($child:cld) {} } lappend tree($node:cld) $child set tree($child:dad) $node } return } proc tree_remove { treevar node } { upvar $treevar tree if { [string equal $tree(root) $node] } { set tree(root) {} foreach child $tree($node:cld) { tree_remove tree $child } } else { set dad $tree($node:dad) tree_remove_child tree $dad $node } unset tree($node:dad) tree($node:cld) } proc tree_remove_child { treevar node child } { upvar $treevar tree set idx [lsearch $tree($node:cld) $node] set tree($node:cld) [lreplace $tree($node:cld) $idx $idx] set tree($child:dad) {} return } proc tree_path { treevar node } { upvar $treevar tree set path {} while { ! [string equal $tree(root) $node] } { set path [linsert $path 0 $node] set node $tree($node:dad) } return [linsert $path 0 $node] }
To test it we can fill it with the following procedure.
proc fill_tree { treevar } { upvar $treevar tree tree_set_root tree 0 tree_add_children tree 0 { 1 2 3 4 5 6 7 8 9 } for {set i 1} {$i < 10} {incr i} { for {set j 1} {$j < 10} {incr j} { tree_add_children tree $i $i.$j for {set k 0} {$k < 10} {incr k} { tree_add_children tree $i.$j $i.$j.$k } } } }
RS: I wouldn't call trees data structures too complex for Tcl (which is implemented in C - our scripts just do the configuration :-) - nested lists are perfectly adequate, compact and efficient for representing tree structures, and easily navigable with multi-index lindex and lset...Marco Maggi: I have to disagree. There are a lot of methods in a tree structure, and most of them require a set of 4/5 (or more) test cases. So if I have to spend time building a reliable structure of such a complexity, I prefer to do it with C, so that I can use the module with and without TCL.I'm writing a C library of data structures, and it's not "fun" to make it reliable: I'm writing a lot of tests (handling them with the tcltest package of course) and spending a lot of hours. I want it to be as much reusable as possible, and C is the answer.I like TCL, but what if tomorrow I get a job and my new boss tells me "Do this with python." ? Or "You have a week to build a C library that does this and that." and I need an AVL tree?My C data structure library will be in my bag of tools "forever".
See also: