Documentation
¶
Index ¶
- type E
- func (t *E[T]) Init(types []string) *E[T]
- func (s *E[T]) JSON() ([]byte, error)
- func (s *E[T]) JSONL() ([]byte, error)
- func (s E[T]) Log()
- func (s E[T]) LogLong()
- func (t *E[T]) Node(typ ...any) *Node[T]
- func (s *E[T]) Print()
- func (s *E[T]) PrintLong()
- func (s E[T]) String() string
- func (s E[T]) StringLong() string
- type Node
- func (n *Node[T]) Add(t int, v T) *Node[T]
- func (n *Node[T]) Append(u *Node[T])
- func (n *Node[T]) Cut() *Node[T]
- func (n *Node[T]) Init()
- func (s *Node[T]) JSON() string
- func (s *Node[T]) JSONL() string
- func (s Node[T]) Log()
- func (s Node[T]) LogL()
- func (s Node[T]) MarshalJSON() ([]byte, error)
- func (n *Node[T]) Morph(c *Node[T])
- func (n *Node[T]) Nodes() []*Node[T]
- func (s *Node[T]) PPrint()
- func (s *Node[T]) Print()
- func (s Node[T]) String() string
- func (n *Node[T]) Take(from *Node[T])
- func (n *Node[T]) WalkDeepPre(do func(n *Node[T]))
- func (n *Node[T]) WalkLevels(do func(n *Node[T]))
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type E ¶ added in v0.4.0
E ("tree-e") is an encapsulating struct to contain the Root Node and all possible Types for any Node. Most users of a tree will make direct use of E.Root (which can safely be swapped out for a root Node reference at any time). Tree implements the rwxrob/json/AsJSON interface and uses custom methods for MarshalJSON and UnmarshalJSON to facilitate storage, transfer, and documentation.
func (*E[T]) Init ¶ added in v0.4.0
Init initializes a tree creating its Root Node reference and assigning it the type of 1 (0 is reserved for UNKNOWN). Init then assigns its Types and indexes the TypesMap.
func (E[T]) LogLong ¶ added in v0.4.0
func (s E[T]) LogLong()
LogLong implements rwxrob/json.Logger.
func (*E[T]) Node ¶ added in v0.4.0
Node returns new detached Node initialized for this same tree. Either an integer or string type may be passed and if none are passed the UNKNOWN (0) type will be assigned.
func (*E[T]) PrintLong ¶ added in v0.4.0
func (s *E[T]) PrintLong()
PrintLong implements rwxrob/json.Printer.
func (E[T]) StringLong ¶ added in v0.4.0
StringLong implements rwxrob/json.Stringer.
type Node ¶
type Node[T any] struct { T int `json:"T"` // type V T `json:",omitempty"` // value P *Node[T] `json:"-"` // up/parent Count int `json:"-"` // node count Tree *E[T] `json:"-"` // optional tree with type names // contains filtered or unexported fields }
Node is an implementation of a "node" from traditional data structures. Nodes can have other nodes under then (which some call being a "parent" (P)). Nodes can also have a value (V). All nodes have a specific integer type (T) (which most will map to constants and slices of strings containing their readable name equivalent). The terms "up", "down", "under", "left", and "right" are consistent with the common visualization of a tree, but are not necessarily constraints on implementation or visual representation. Node is implemented as a linked list for maximum performance. Also see tree.
Example ¶
package main import ( "fmt" "github.com/rwxrob/structs/tree" "github.com/rwxrob/structs/types" ) func main() { // flexible n := new(tree.Node[any]) n.Print() // specific m := new(tree.Node[int]) m.Print() // default type: UNKNOWN == 0 fmt.Println(n.T == types.UNKNOWN, m.T == types.UNKNOWN) // values matching zero value are omitted }
Output: {"T":0} {"T":0} true true
Example (Properties) ¶
package main import ( "fmt" "github.com/rwxrob/structs/tree" ) func main() { // Nodes have these properties updating every time // their state is changed so that queries need not // to the checks again later. // initial state n := new(tree.Node[any]) fmt.Println("n:", n.P == nil, n.V, n.Count) u := n.Add(1, nil) fmt.Println("n:", n.P == nil, n.V, n.Count) fmt.Println("u:", u.P == nil, u.V, u.Count) // make an edge node u.V = "something" // break edge by forcing it to have nodes and a value (discouraged) u.Add(9001, "muhaha") fmt.Println("u:", u.P == nil, u.V, u.Count) }
Output: n: true <nil> 0 n: true <nil> 1 u: false <nil> 0 u: false something 1
Example (Type_is_Integer) ¶
package main import ( "github.com/rwxrob/structs/tree" ) func main() { n := new(tree.Node[any]) n.T = 1 n.Print() //n.T = "one" // BOOM! }
Output: {"T":1}
Example (Value_Depends_on_Instantiation) ¶
package main import ( "github.com/rwxrob/structs/tree" ) func main() { z := new(tree.Node[any]) z.Print() // values that are equiv of zero value for type are omitted // flexible n := new(tree.Node[any]) n.V = 1 n.Print() n.V = true n.Print() n.V = "foo" n.Print() // strict m := new(tree.Node[int]) m.V = 1 m.Print() //m.V = true // BOOM! }
Output: {"T":0} {"T":0,"V":1} {"T":0,"V":true} {"T":0,"V":"foo"} {"T":0,"V":1}
func (*Node[T]) Add ¶
Add creates a new Node with type and value under and returns. It also updates Count.
func (*Node[T]) Cut ¶
Cut removes a Node from under the one above it and returns.
Example (First) ¶
package main import ( "github.com/rwxrob/structs/tree" ) func main() { n := new(tree.Node[any]) c := n.Add(1, nil) n.Add(2, nil) n.Add(3, nil) n.Print() x := c.Cut() n.Print() x.Print() }
Output: {"T":0,"N":[{"T":1},{"T":2},{"T":3}]} {"T":0,"N":[{"T":2},{"T":3}]} {"T":1}
Example (Last) ¶
package main import ( "github.com/rwxrob/structs/tree" ) func main() { n := new(tree.Node[any]) n.Add(1, nil) n.Add(2, nil) c := n.Add(3, nil) n.Print() x := c.Cut() n.Print() x.Print() }
Output: {"T":0,"N":[{"T":1},{"T":2},{"T":3}]} {"T":0,"N":[{"T":1},{"T":2}]} {"T":3}
Example (Middle) ¶
package main import ( "fmt" "github.com/rwxrob/structs/tree" ) func main() { n := new(tree.Node[any]) n.Add(1, nil) c := n.Add(2, nil) n.Add(3, nil) n.Print() fmt.Println(n.Count) x := c.Cut() n.Print() fmt.Println(n.Count) x.Print() }
Output: {"T":0,"N":[{"T":1},{"T":2},{"T":3}]} 3 {"T":0,"N":[{"T":1},{"T":3}]} 2 {"T":2}
func (*Node[T]) Init ¶
func (n *Node[T]) Init()
Init resets the node to its empty/zero state as if just created for the first time.
Example ¶
package main import ( "fmt" "github.com/rwxrob/structs/tree" ) func main() { // create and print a brand new one n := new(tree.Node[any]) n.Print() // add something to it n.V = "something" n.Print() // initialize it back to "empty" n.Init() n.Print() // now try with something with a tricker zero value n.V = func() {} // log.Println(n.V) // "0x5019e0" yep it's there // n.Print() // would log error and fail to marshal JSON // check it's properties fmt.Println(n.P != nil, n.Count) }
Output: {"T":0} {"T":0,"V":"something"} {"T":0} false 0
func (Node[T]) MarshalJSON ¶
MarshalJSON implements encoding/json.Marshaler and it needed to fulfill the list of nodes since they are internally stored as a linked list.
func (*Node[T]) Morph ¶
Morph initializes the node with Init and then sets it's value (V) and type (T) and all of its attachment references to those of the Node passed thereby preserving the Node reference of this method's receiver.
Example ¶
package main import ( "github.com/rwxrob/structs/tree" ) func main() { n := new(tree.Node[any]) n.Add(2, "some") m := new(tree.Node[any]) m.Morph(n) n.Print() m.Print() }
Output: {"T":0,"N":[{"T":2,"V":"some"}]} {"T":0,"N":[{"T":2,"V":"some"}]}
func (*Node[T]) Nodes ¶
Nodes returns all the nodes under this Node. Prefer checking Count when the values are not needed.
Example ¶
package main import ( "fmt" "github.com/rwxrob/structs/tree" ) func main() { // create the first tree n := new(tree.Node[any]) n.Add(1, nil) n.Add(2, nil) fmt.Println(n.Nodes(), n.Count) // and another added under it m := n.Add(3, nil) m.Add(3, nil) m.Add(3, nil) fmt.Println(m.Nodes(), m.Count) }
Output: [{"T":1} {"T":2}] 2 [{"T":3} {"T":3}] 2
func (*Node[T]) Take ¶
Take moves all nodes from another under itself.
Example ¶
package main import ( "fmt" "github.com/rwxrob/structs/tree" ) func main() { // build up the first n := new(tree.Node[any]) n.T = 10 n.Add(1, nil) n.Add(2, nil) n.Add(3, nil) n.Print() fmt.Println(n.Count) // now take them over m := new(tree.Node[any]) m.T = 20 m.Print() fmt.Println(m.Count) m.Take(n) m.Print() fmt.Println(m.Count) n.Print() fmt.Println(n.Count) }
Output: {"T":10,"N":[{"T":1},{"T":2},{"T":3}]} 3 {"T":20} 0 {"T":20,"N":[{"T":1},{"T":2},{"T":3}]} 3 {"T":10} 0
func (*Node[T]) WalkDeepPre ¶
WalkDeepPre will pass each Node in the tree to the given function traversing in a synchronous, depth-first, preorder way. The function passed may be a closure containing variables, contexts, or a channel outside of its own scope to be updated for each visit. This method uses functional recursion which may have some limitations depending on the depth of node trees required.
Example ¶
package main import ( "fmt" "github.com/rwxrob/structs/tree" ) func main() { n := new(tree.Node[any]) n.Add(1, nil).Add(11, nil) n.Add(2, nil).Add(22, nil) n.Add(3, nil).Add(33, nil) n.WalkDeepPre(func(c *tree.Node[any]) { fmt.Print(c.T, " ") }) }
Output: 0 1 11 2 22 3 33
func (*Node[T]) WalkLevels ¶
WalkLevels will pass each Node in the tree to the given function traversing in a synchronous, breadth-first, leveler way. The function passed may be a closure containing variables, contexts, or a channel outside of its own scope to be updated for each visit. This method uses functional recursion which may have some limitations depending on the depth of node trees required.
Example ¶
package main import ( "fmt" "github.com/rwxrob/structs/tree" ) func main() { n := new(tree.Node[any]) n.Add(1, nil).Add(11, nil) n.Add(2, nil).Add(22, nil) n.Add(3, nil).Add(33, nil) n.WalkLevels(func(c *tree.Node[any]) { fmt.Print(c.T, " ") }) }
Output: 0 1 2 3 11 22 33