NaryTree v0.1.1 NaryTree View Source
NaryTree implements a data structure for an n-ary tree in which each node has zero or more children. A node in a tree can have arbitrary number of children and depth. Trees are unbalanced and children unordered.
Link to this section Summary
Functions
Add a child node to a tree root node. Returns an updated tree with added child
Add a child node to the specified tree node. Returns an updated tree with added child
Returns the children nodes of a tree
Delete a node in a tree. If the deleted node has children, the children will be moved up in hierarchy to become the children of the deleted node’s parent
Detach a branch in a tree. Returns the detached branch conplete with all its descendents as a new tree struct
Enumerates tree nodes, and applies function to each leaf nodes’ content.
Similar to update_content/2
, but applies only to leaf nodes
Invoked in order to access the value stored under key
in the given term term
Converts a map into a tree
Get the node with the specified id from the tree
Invoked in order to access a node in a tree and update it at the same time
Check whether a node has non-empty content
Check whether a node is a leaf node
Check whether the argument is of NaryTree type
Check whether a node is a root node
Converts a list of nodes back into nodes map %{node1id => %NaryTree.Node{}, node2id => ...}
Merges a tree into another tree at the specified node point.
Returns the resulting combined tree or :error
if the specified
node point doesn’t exist
Move children nodes from one node to another node
Create a new, empty tree
Create a new tree with a root node
Returns the parent node of a tree, or :empty
if there is none
Invoked to “pop” the specified node from the tree
Prints a tree in hierarchical fashion.
The second parameter is an optional function that accepts a node as a parameter.
print_tree
will output the return value of the function for each node in the tree
Put a node into the tree at the specified id. Put will replace the name and content attributes of the node at id with the attributes of the new nodes. The children and parent of the old node will remain the same so that the hierarchy structure remains the same
Returns the root node of a tree
Returns the sibling nodes of a node
Collects nodes of a tree by using depth-first traversal. Returns a list of NaryTree.Node
structs
Converts a tree into a hierarchical map with children nodes embedded in an array
Enumerates tree nodes, and applies function to each node’s content. Returns updated tree, with new content for every nodes
Link to this section Types
Link to this section Functions
add_child(NaryTree.t(), NaryTree.Node.t()) :: NaryTree.t()
Add a child node to a tree root node. Returns an updated tree with added child.
RootNode
\
ChildNode
Example
iex> tree = NaryTree.new(NaryTree.Node.new "Root node") |>
...> NaryTree.add_child(NaryTree.Node.new("Child"))
iex> %NaryTree{root: key, nodes: nodes} = tree
iex> [child_id | _] = nodes[key].children
iex> nodes[child_id].name
"Child"
Add a child node to the specified tree node. Returns an updated tree with added child.
RootNode
\
BranchNode
\
New node
Example
iex> branch = NaryTree.Node.new("Branch Node")
iex> tree = NaryTree.new(NaryTree.Node.new("Root Node")) |>
...> NaryTree.add_child(branch) |>
...> NaryTree.add_child(NaryTree.Node.new("New node"), branch.id)
iex> Enum.count tree.nodes
3
Returns the children nodes of a tree.
Delete a node in a tree. If the deleted node has children, the children will be moved up in hierarchy to become the children of the deleted node’s parent.
Deleting root node results in :error
Example
iex> branch = NaryTree.Node.new("Branch Node")
iex> leaf = NaryTree.Node.new("Leaf")
iex> tree = NaryTree.new(NaryTree.Node.new("Root Node")) |>
...> NaryTree.add_child(branch) |>
...> NaryTree.add_child(leaf, branch.id) |>
...> NaryTree.delete(branch.id)
iex> tree.nodes[branch.id]
nil
iex> tree.nodes[tree.root].children # leaf becomes root's child
[leaf.id]
Detach a branch in a tree. Returns the detached branch conplete with all its descendents as a new tree struct.
Example
iex> branch = NaryTree.Node.new("Branch Node")
iex> leaf = NaryTree.Node.new("Leaf")
iex> tree = NaryTree.new(NaryTree.Node.new("Root Node")) |>
...> NaryTree.add_child(branch) |>
...> NaryTree.add_child(leaf, branch.id)
iex> detached = NaryTree.detach(tree, branch.id)
iex> Enum.count detached.nodes
2
iex> detached.root
branch.id
each_leaf(NaryTree.t(), function()) :: NaryTree.t()
Enumerates tree nodes, and applies function to each leaf nodes’ content.
Similar to update_content/2
, but applies only to leaf nodes.
fetch(NaryTree.t(), String.t()) :: {:ok, NaryTree.Node.t()} | :error
Invoked in order to access the value stored under key
in the given term term
.
This function should return {:ok, value}
where value
is the value under
key
if the key exists in the term, or :error
if the key does not exist in
the term.
Many of the functions defined in the Access
module internally call this
function. This function is also used when the square-brackets access syntax
(structure[key]
) is used: the fetch/2
callback implemented by the module
that defines the structure
struct is invoked and if it returns {:ok,
value}
then value
is returned, or if it returns :error
then nil
is
returned.
See the Map.fetch/2
and Keyword.fetch/2
implementations for examples of
how to implement this callback.
Callback implementation for Access.fetch/2
.
Converts a map into a tree
Example:
iex> tree = NaryTree.from_map %{name: “Root”, children: [%{name: “Left”}, %{name: “Right”}]} iex> Enum.count tree 3
Get the node with the specified id from the tree.
Example
iex> node = NaryTree.Node.new("Node")
iex> n = NaryTree.new(node) |>
...> NaryTree.get(node.id)
iex> n.name
"Node"
Invoked in order to access a node in a tree and update it at the same time
Example
iex> tree = NaryTree.new NaryTree.Node.new "Root"
iex> {old_node, new_tree} = NaryTree.get_and_update tree, tree.root, &({&1, %NaryTree.Node{&1 | content: :not_empty}})
iex> old_node.content
:empty
iex> NaryTree.root(new_tree).content
:not_empty
Check whether a node has non-empty content.
Example
iex> node = NaryTree.Node.new "Node", content: %{c: "Content"}
iex> NaryTree.has_content? node
true
Check whether a node is a leaf node.
Example
iex> tree = NaryTree.new(NaryTree.Node.new("Root node")) |>
...> NaryTree.add_child(NaryTree.Node.new("Leaf node"))
iex> [node_id] = tree.nodes[tree.root].children
iex> leaf_node = tree.nodes[node_id]
iex> NaryTree.is_leaf? leaf_node
true
Check whether the argument is of NaryTree type.
Example
iex> NaryTree.is_nary_tree? NaryTree.new(NaryTree.Node.new "Node")
true
Check whether a node is a root node.
Example
iex> node = NaryTree.Node.new "Root node"
iex> NaryTree.is_root? node
true
Converts a list of nodes back into nodes map %{node1id => %NaryTree.Node{}, node2id => ...}
Merges a tree into another tree at the specified node point.
Returns the resulting combined tree or :error
if the specified
node point doesn’t exist.
Example
iex> branch = NaryTree.Node.new("Branch Node")
iex> tree1 = NaryTree.new(NaryTree.Node.new("Root Node")) |>
...> NaryTree.add_child(branch)
iex> tree2 = NaryTree.new(NaryTree.Node.new("Subtree")) |>
...> NaryTree.add_child(NaryTree.Node.new("Leaf"))
iex> combined = NaryTree.merge(tree1, tree2, branch.id)
iex> Enum.count combined.nodes
4
move_nodes(NaryTree.t(), [NaryTree.Node.t()], NaryTree.Node.t()) :: NaryTree.t()
move_nodes(NaryTree.t(), [String.t()], String.t()) :: NaryTree.t()
Move children nodes from one node to another node.
Create a new tree with a root node.
Example
iex> %NaryTree{root: key, nodes: nodes} = NaryTree.new(NaryTree.Node.new "Root node")
iex> nodes[key].name
"Root node"
Returns the parent node of a tree, or :empty
if there is none
Example
iex> branch = NaryTree.Node.new("Branch Node")
iex> tree = NaryTree.new(NaryTree.Node.new("Root Node")) |>
...> NaryTree.add_child(branch)
iex> %NaryTree.Node{name: name} = NaryTree.root(tree)
iex> name
"Root Node"
Invoked to “pop” the specified node from the tree.
When key exists in the tree, it returns a {a_node, new_tree}
tuple where a_node
is the node that was under key and new_tree
is the tree without a_node
.
When key is not present in the tree, it returns {nil, tree}
.
Prints a tree in hierarchical fashion.
The second parameter is an optional function that accepts a node as a parameter.
print_tree
will output the return value of the function for each node in the tree.
Example
iex> NaryTree.print_tree tree, fn(node) -> "#{x.name} : {x.content}" end
or
iex> NaryTree.print_tree tree, &("#{&1.name}: #{&1.id}")
Put a node into the tree at the specified id. Put will replace the name and content attributes of the node at id with the attributes of the new nodes. The children and parent of the old node will remain the same so that the hierarchy structure remains the same.
Example
iex> tree = NaryTree.new NaryTree.Node.new("Root")
iex> tree.nodes[tree.root].name
"Root"
iex> tree = NaryTree.put(tree, tree.root, NaryTree.Node.new("Node"))
iex> tree.nodes[tree.root].name
"Node"
Returns the root node of a tree.
Example
iex> tree = NaryTree.new(NaryTree.Node.new("Root Node"))
iex> %NaryTree.Node{name: name} = NaryTree.root(tree)
iex> name
"Root Node"
Returns the sibling nodes of a node.
Collects nodes of a tree by using depth-first traversal. Returns a list of NaryTree.Node
structs
Converts a tree into a hierarchical map with children nodes embedded in an array.
Takes tree as argument, and an optional function. The function takes a node parameter and should return a map of attributes.
The default function returns
%{id: node.id, name: node.name, content: node.content, level: node.level, parent: node.parent}
Example
iex> tree = NaryTree.new(NaryTree.Node.new("Root")) |>
...> NaryTree.add_child(NaryTree.Node.new("Leaf 1")) |>
...> NaryTree.add_child(NaryTree.Node.new("Leaf 2")) |>
...> NaryTree.to_map( &(%{key: &1.name}) )
%{children: [%{key: "Leaf 1"}, %{key: "Leaf 2"}], key: "Root"}
update_content(NaryTree.t(), function()) :: NaryTree.t()
Enumerates tree nodes, and applies function to each node’s content. Returns updated tree, with new content for every nodes
Example
iex> tree = NaryTree.new(NaryTree.Node.new("Root node")) |>
...> NaryTree.add_child(NaryTree.Node.new("Leaf node 1")) |>
...> NaryTree.add_child(NaryTree.Node.new("Leaf node 2"))
iex> Enum.map tree.nodes, fn({_,node}) -> node.content end
[:empty, :empty, :empty]
iex> NaryTree.update_content(tree, fn(_) -> %{x: 4} end) |>
...> Map.get(:nodes) |> Enum.map(fn({_,node}) -> node.content end)
[%{x: 4}, %{x: 4}, %{x: 4}]