-
Notifications
You must be signed in to change notification settings - Fork 0
/
labyrinth.go
162 lines (145 loc) · 5.05 KB
/
labyrinth.go
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package main
import (
"fmt"
)
func main() {
/* Initialization of structure. Root addition. */
labyrinth := &Node{Val: 100, L: nil, R: nil,
M: &Meta{ThreadS: []string{"."}, AssocN: map[int][]string{
100: {"."}},
},
}
fmt.Printf("\nCreate Labyrinth, Adding Values\n")
fmt.Printf("Working on %v (ROOT)... %v added. ThreadS Route: %v\n",
labyrinth.Val, labyrinth.Val, labyrinth.M.ThreadS)
/* Add values to labyrinth */
values := []int{19, 7, 24, 150, 140, 276, 199, 2, 144}
for _, v := range values {
thrStr := make([]string, 0) // Create [] with make - Strings
thrStr = append(thrStr, ".") // Init value of "." for Root
fmt.Printf("Working on %3d... ", v)
// Add Node (as key) and thread (as value) at the top level map
labyrinth.M.AssocN[v] = labyrinth.AddNode(v, thrStr)
}
fmt.Printf("Entire Map: %v\n\n", labyrinth.M.AssocN)
/* Thraverse the entire tree */
labyrinth.Traverse()
/* Search for specific values NOT USING Binary search. */
labyrinth.Search(100)
labyrinth.Search(1561)
labyrinth.Search(140)
labyrinth.Search(199)
labyrinth.Search(7)
labyrinth.Search(19)
}
// Node struct as the main tree struct
type Node struct {
Val int // Value of Node/Leaf
L *Node // Left node
R *Node // Right node
M *Meta // Meta data embedded struct
}
// Meta struct monitoring the routing information of the node/leaf
type Meta struct {
ThreadS []string // Thread with strings
AssocN map[int][]string // Associates Node values with thread(s)
}
// Method Search() on *Node type. With receivers argument list of type *Node,
// named n. Method search if node exists, and returns true/false and entire path.
// Then, it goes to the Node, by calling the WalkTheLabyrinth() method.
func (n *Node) Search(key int) {
// Search the map with Node value as key. If ok, then the Node exists ...
if v, ok := n.M.AssocN[key]; ok {
fmt.Printf("Node %v exist.\tThread: %v ... ", key, v)
// If Node found on map, and it's not the Root, GO TO that Node ->
if l := len(v); l > 1 {
v = v[1:] // Cut the first "." (the root)
fmt.Printf("%v\n", n.WalkTheLabyrinth(v)) // Pass the rest []
} else {
fmt.Printf("%v %t (ROOT)\n", n.Val, true) // else, it's the Root Node
}
} else {
// ... if not, it doesn't exist at all. We dont's have to search the tree!!!
fmt.Printf("Node %v doesn't exist.\n", key)
}
}
// Method WalkTheLabirynth() on *Note type. With receivers arguments list
// of *Node, named n. Searches for specific node.
func (n *Node) WalkTheLabyrinth(thread []string) bool {
if l := len(thread); l == 0 { // If length is 0, we reach the Node
fmt.Printf("%v ", n.Val)
return true
}
// In every recursion call, we re-slice the []thread low bound by 1
switch thread[0] {
case "L":
return n.L.WalkTheLabyrinth(thread[1:]) // Tail Recursive for left *Node
case "R":
return n.R.WalkTheLabyrinth(thread[1:]) // Tail Recursive for right *Node
}
return false
}
// Method Traverse() on *Node struct type. With receiver argument list
// of type *Node, named n. Dumps the entire tree.
func (n *Node) Traverse() {
if n == nil {
fmt.Printf("Receiver is <nil>\n\n")
return
}
switch {
case n.L != nil && n.R != nil:
fmt.Printf("Node: %3d Thread: %v\tChild: (L: %v, R: %v)\n",
n.Val, n.M.ThreadS, n.L.Val, n.R.Val)
case n.L == nil && n.R == nil:
fmt.Printf("Node: %3d Thread: %v\tChild: (L: %v, R: %v)\n",
n.Val, n.M.ThreadS, "<nil>", "<nil>")
case n.L == nil && n.R != nil:
fmt.Printf("Node: %3d Thread: %v\tChild: (L: %v, R: %v)\n",
n.Val, n.M.ThreadS, "<nil>", n.R.Val)
case n.L != nil && n.R == nil:
fmt.Printf("Node: %3d Thread: %v\tChild: (L: %v, R: %v)\n",
n.Val, n.M.ThreadS, n.L.Val, "<nil>")
}
if n.L != nil || n.R != nil {
n.L.Traverse()
n.R.Traverse()
}
}
// Method AddNode on Node struct type. With receiver Argument List
// of type *Node, named n. Duplicates NOT allowed.
func (n *Node) AddNode(v int, thrStr []string) []string {
switch {
/* Found on root */
case v == n.Val:
fmt.Printf("Value: %v found on root: (%v). Thread: %v\n",
v, n.Val, n.M.ThreadS)
/* Go to left Node */
case v < n.Val:
thrStr = append(thrStr, "L") // Update the []thread with Left move
switch {
case n.L == nil:
// add LEFT node and the thread of it, at the currect level's Node fields
n.L = &Node{Val: v, M: &Meta{ThreadS: thrStr}, L: nil, R: nil}
fmt.Printf("\t%3d added. Thread: %v\n", n.L.Val, n.L.M.ThreadS)
case v == n.L.Val:
fmt.Printf("Value %v already exists (%v)\n", v, n.L.Val)
default:
return n.L.AddNode(v, thrStr)
}
/* Go to right Node */
case v > n.Val:
thrStr = append(thrStr, "R") // Update the []thread with Right move
switch {
case n.R == nil:
// add RIGHT node and the thread of it, at the currect level's Node fields
n.R = &Node{Val: v, M: &Meta{ThreadS: thrStr}, L: nil, R: nil}
fmt.Printf("\t%3d added. Thread: %v\n", n.R.Val, n.R.M.ThreadS)
case v == n.R.Val:
fmt.Printf("Value %v already exists (%v)\n", v, n.R.Val)
default:
return n.R.AddNode(v, thrStr)
}
}
// Return the thread to be added as value to the main map
return thrStr
}