File: rosetta-tree.tcl

package info (click to toggle)
nsf 2.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 12,628 kB
  • sloc: ansic: 32,245; tcl: 10,636; sh: 664; pascal: 176; lisp: 41; makefile: 24
file content (92 lines) | stat: -rw-r--r-- 2,950 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#
# == Rosetta example: https://rosettacode.org/wiki/Tree_traversal
#
#
# Implement a binary tree structure, with each node carrying an
# integer as a node label, and four traversal strategies: pre-order,
# in-order, postorder, and levelorder traversals.
# 
# https://rosettacode.org/wiki/Tree_traversal
#

package req nx
package req nx::test

#
# The class +Tree+ implements the basic binary composite structure (left, right).
#

nx::Class create Tree {
    :property -accessor public value:required
    :property -accessor public left:object,type=[current]
    :property -accessor public right:object,type=[current]

    :public method traverse {order} {
	set list {}
	:$order v {
	    lappend list $v
	}
	return $list
    }
 
    # Traversal methods
    :public method preOrder {varName script {level 0}} {
	upvar [incr level] $varName var
	set var ${:value}
	uplevel $level $script
	if {[info exists :left]} {${:left} preOrder $varName $script $level}
	if {[info exists :right]} {${:right} preOrder $varName $script $level}
    }
    
    :public method inOrder {varName script {level 0}} {
	upvar [incr level] $varName var
	if {[info exists :left]} {${:left} inOrder $varName $script $level}
	set var ${:value}
	uplevel $level $script
	if {[info exists :right]} {${:right} inOrder $varName $script $level}
    }
    :public method postOrder {varName script {level 0}} {
	upvar [incr level] $varName var
	if {[info exists :left]} {${:left} postOrder $varName $script $level}
	if {[info exists :right]} {${:right} postOrder $varName $script $level}
	set var ${:value}
	uplevel $level $script
    }
    :public method levelOrder {varName script} {
	upvar 1 $varName var
	set nodes [list [current]]
	while {[llength $nodes] > 0} {
	    set nodes [lassign $nodes n]
	    set var [$n value get]
	    uplevel 1 $script
	    if {[$n eval {info exists :left}]} {lappend nodes [$n left get]}
	    if {[$n eval {info exists :right}]} {lappend nodes [$n right get]}
	}
    }
}

#
# This is a factory method to build up the object tree recursively
# from a nested Tcl list. Note that we create left and right children by
# nesting them in their parent, this provides for a cascading cleanup
# of an entire tree (there is no need for an explicit cascading of
# +destroy+ methods down the composite).
#

Tree public object method newFromList {-parent l} {
    lassign $l value left right
    set n [:new {*}[expr {[info exists parent]?[list -childof $parent]:""}] -value $value]
    set props [list]
    if {$left ne ""} {lappend props -left [:newFromList -parent $n $left]}
    if {$right ne ""} {lappend props -right [:newFromList -parent $n $right]}
    $n configure {*}$props
    return $n
}

# Run the required tests:

set t [Tree newFromList {1 {2 {4 7} 5} {3 {6 8 9}}}]
? {$t traverse preOrder} {1 2 4 7 5 3 6 8 9}
? {$t traverse inOrder} {7 4 2 5 1 8 6 9 3}
? {$t traverse postOrder}  {7 4 5 2 8 9 6 3 1}
? {$t traverse levelOrder} {1 2 3 4 5 6 7 8 9}