ucx
UAP Common Extensions
Loading...
Searching...
No Matches
tree.h File Reference

Interface for tree implementations. More...

#include "common.h"
#include "collection.h"

Go to the source code of this file.

Data Structures

struct  cx_tree_visitor_queue_s
 An element in a visitor queue. More...
 
struct  cx_tree_combined_iterator_s
 An iterator (DFS) or visitor (BFS) for a tree. More...
 
struct  cx_tree_node_base_s
 Base structure that can be used for tree nodes in a CxTree. More...
 
struct  cx_tree_s
 Structure for holding the base data of a tree. More...
 

Macros

#define cxTreeIteratorContinue(iterator)
 Advises the iterator to skip the subtree below the current node and also continues the current loop.
 
#define CX_TREE_SEARCH_INFINITE_DEPTH   0
 Macro that can be used instead of the magic value for infinite search depth.
 
#define CX_TREE_NODE(type)
 Macro to roll out the cx_tree_node_base_s structure with a custom node type.
 
#define cx_tree_node_layout(struct_name)
 Macro for specifying the layout of a tree node.
 

Typedefs

typedef struct cx_tree_combined_iterator_s CxTreeIterator
 An iterator (DFS) or visitor (BFS) for a tree.
 
typedef int(* cx_tree_search_func) (const void *node, const void *data)
 Function pointer for a search function.
 
typedef struct cx_tree_s CxTree
 Structure for holding the base data of a tree.
 
typedef void(* cx_tree_relink_func) (void *node, const void *old_parent, const void *new_parent)
 A function that is invoked when a node needs to be re-linked to a new parent.
 

Functions

void cxTreeIteratorDispose (CxTreeIterator *iter)
 Releases internal memory of the given tree iterator.
 
void cx_tree_add (void *parent, void *node, ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, ptrdiff_t loc_prev, ptrdiff_t loc_next)
 Links a node to a (new) parent.
 
void cx_tree_remove (void *node, ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, ptrdiff_t loc_prev, ptrdiff_t loc_next)
 Unlinks a node from its parent.
 
int cx_tree_search (const void *root, size_t max_depth, const void *data, cx_tree_search_func sfunc, void **result, ptrdiff_t loc_children, ptrdiff_t loc_next)
 Searches for data in a tree.
 
CxTreeIterator cx_tree_iterator (void *root, bool visit_on_exit, ptrdiff_t loc_children, ptrdiff_t loc_next)
 Creates a depth-first iterator for a tree with the specified root node.
 
CxTreeIterator cx_tree_visitor (void *root, ptrdiff_t loc_children, ptrdiff_t loc_next)
 Creates a breadth-first iterator for a tree with the specified root node.
 
void cxTreeDestroySubtree (CxTree *tree, void *node)
 Destroys a node and its subtree.
 
static void cxTreeClear (CxTree *tree)
 Destroys the tree contents.
 
void cxTreeFree (CxTree *tree)
 Deallocates the tree structure.
 
CxTreecxTreeCreate (const CxAllocator *allocator, size_t node_size, size_t elem_size, void *root, ptrdiff_t loc_data, ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, ptrdiff_t loc_prev, ptrdiff_t loc_next)
 Creates a new tree.
 
void * cxTreeFindInSubtree (CxTree *tree, const void *data, void *subtree_root, size_t max_depth, bool use_dfs)
 Searches the data in the specified subtree.
 
static void * cxTreeFind (CxTree *tree, const void *data, bool use_dfs)
 Searches the data in the specified tree.
 
void * cxTreeFindFastInSubtree (CxTree *tree, const void *data, cx_tree_search_func sfunc, void *subtree_root, size_t max_depth)
 Performs an efficient depth-first search in a branch of the specified tree.
 
static void * cxTreeFindFast (CxTree *tree, const void *data, cx_tree_search_func sfunc)
 Performs an efficient depth-first search in the tree.
 
size_t cxTreeSubtreeSize (CxTree *tree, void *subtree_root)
 Determines the size of the specified subtree.
 
size_t cxTreeSubtreeDepth (CxTree *tree, void *subtree_root)
 Determines the depth of the specified subtree.
 
size_t cxTreeSize (CxTree *tree)
 Determines the size of the entire tree.
 
size_t cxTreeDepth (CxTree *tree)
 Determines the depth of the entire tree.
 
CxTreeIterator cxTreeIterateSubtree (CxTree *tree, void *node, bool visit_on_exit)
 Creates a depth-first iterator for the specified tree starting in node.
 
CxTreeIterator cxTreeVisitSubtree (CxTree *tree, void *node)
 Creates a breadth-first iterator for the specified tree starting in node.
 
CxTreeIterator cxTreeIterate (CxTree *tree, bool visit_on_exit)
 Creates a depth-first iterator for the specified tree.
 
CxTreeIterator cxTreeVisit (CxTree *tree)
 Creates a breadth-first iterator for the specified tree.
 
void cxTreeSetParent (CxTree *tree, void *parent, void *child)
 Sets the (new) parent of the specified child.
 
void cxTreeAddNode (CxTree *tree, void *parent, void *child)
 Adds a new node to the tree.
 
void * cxTreeAddData (CxTree *tree, void *parent, const void *data)
 Creates a new node and adds it to the tree.
 
void * cxTreeCreateNode (CxTree *tree, void *parent)
 Creates a new node and adds it to the tree.
 
void * cxTreeCreateRoot (CxTree *tree)
 Creates a new root node or returns the existing root node.
 
void * cxTreeCreateRootData (CxTree *tree, const void *data)
 Creates a new root node or uses the existing root node and writes the specified data to that node.
 
void * cxTreeSetRoot (CxTree *tree, void *new_root)
 Exchanges the root of the tree.
 
int cxTreeRemoveNode (CxTree *tree, void *node, cx_tree_relink_func relink_func)
 Removes a node and re-links its children to its former parent.
 
void cxTreeRemoveSubtree (CxTree *tree, void *node)
 Removes a node and its subtree from the tree.
 
int cxTreeDestroyNode (CxTree *tree, void *node, cx_tree_relink_func relink_func)
 Destroys a node and re-links its children to its former parent.
 

Detailed Description

Interface for tree implementations.

Author
Mike Becker
Olaf Wintermann

Macro Definition Documentation

◆ CX_TREE_NODE

#define CX_TREE_NODE ( type)
Value:
type *parent; \
type *children;\
type *last_child;\
type *prev;\
type *next

Macro to roll out the cx_tree_node_base_s structure with a custom node type.

Must be used as the first member in your custom tree struct.

Parameters
typethe data type for the nodes

◆ cx_tree_node_layout

#define cx_tree_node_layout ( struct_name)
Value:
offsetof(struct_name, parent),\
offsetof(struct_name, children),\
offsetof(struct_name, last_child),\
offsetof(struct_name, prev), \
offsetof(struct_name, next)

Macro for specifying the layout of a tree node.

When your tree uses CX_TREE_NODE, you can use this macro in all tree functions that expect the layout parameters loc_parent, loc_children, loc_last_child, loc_prev, and loc_next.

Parameters
struct_namethe name of the node structure

◆ cxTreeIteratorContinue

#define cxTreeIteratorContinue ( iterator)
Value:
(iterator).skip = true; continue

Advises the iterator to skip the subtree below the current node and also continues the current loop.

Parameters
iterator(CxTreeIterator) the iterator

Typedef Documentation

◆ cx_tree_relink_func

typedef void(* cx_tree_relink_func) (void *node, const void *old_parent, const void *new_parent)

A function that is invoked when a node needs to be re-linked to a new parent.

When a node is re-linked, sometimes the contents need to be updated. This callback is invoked by cxTreeRemoveNode() and cxTreeDestroyNode() so that those updates can be applied when re-linking the children of the removed node.

Parameters
nodethe affected node
old_parentthe old parent of the node
new_parentthe new parent of the node

◆ cx_tree_search_func

typedef int(* cx_tree_search_func) (const void *node, const void *data)

Function pointer for a search function.

A function of this kind shall check if the specified node contains the given data or if one of the children might contain the data.

The function should use the returned integer to indicate how close the match is, where a negative number means that it does not match at all. Zero means exact match and a positive number is an implementation defined measure for the distance to an exact match.

For example, consider a tree that stores file path information. A node which is describing a parent directory of a searched file shall return a positive number to indicate that a child node might contain the searched item. On the other hand, if the node denotes a path that is not a prefix of the searched filename, the function would return -1 to indicate that the search does not need to be continued in that branch.

Parameters
nodethe node that is currently investigated
datathe data that is searched for
Returns
0 if the node contains the data, positive if one of the children might contain the data, negative if neither the node nor the children contains the data

Function Documentation

◆ cx_tree_add()

void cx_tree_add ( void * parent,
void * node,
ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
ptrdiff_t loc_prev,
ptrdiff_t loc_next )

Links a node to a (new) parent.

If the node already has a parent, it is unlinked, first. If the parent has children already, the node is appended to the list of all currently existing children.

Parameters
parentthe parent node
nodethe node that shall be linked
loc_parentoffset in the node struct for the parent pointer
loc_childrenoffset in the node struct for the children linked list
loc_last_childoptional offset in the node struct for the pointer to the last child in the linked list (negative if there is no such pointer)
loc_prevoptional offset in the node struct for the prev pointer
loc_nextoffset in the node struct for the next pointer
See also
cx_tree_remove()

◆ cx_tree_iterator()

CxTreeIterator cx_tree_iterator ( void * root,
bool visit_on_exit,
ptrdiff_t loc_children,
ptrdiff_t loc_next )

Creates a depth-first iterator for a tree with the specified root node.

Note
A tree iterator needs to maintain a stack of visited nodes, which is allocated using the cxDefaultAllocator. When the iterator becomes invalid, this memory is automatically released. However, if you wish to cancel the iteration before the iterator becomes invalid by itself, you MUST call cxTreeIteratorDispose() manually to release the memory.
Remarks
The returned iterator does not support cxIteratorFlagRemoval().
Parameters
rootthe root node
visit_on_exitset to true, when the iterator shall visit a node again after processing all children
loc_childrenoffset in the node struct for the children linked list
loc_nextoffset in the node struct for the next pointer
Returns
the new tree iterator
See also
cxTreeIteratorDispose()

◆ cx_tree_remove()

void cx_tree_remove ( void * node,
ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
ptrdiff_t loc_prev,
ptrdiff_t loc_next )

Unlinks a node from its parent.

If the node has no parent, this function does nothing.

Parameters
nodethe node that shall be unlinked from its parent
loc_parentoffset in the node struct for the parent pointer
loc_childrenoffset in the node struct for the children linked list
loc_last_childoptional offset in the node struct for the pointer to the last child in the linked list (negative if there is no such pointer)
loc_prevoptional offset in the node struct for the prev pointer
loc_nextoffset in the node struct for the next pointer
See also
cx_tree_add()

◆ cx_tree_search()

int cx_tree_search ( const void * root,
size_t max_depth,
const void * data,
cx_tree_search_func sfunc,
void ** result,
ptrdiff_t loc_children,
ptrdiff_t loc_next )

Searches for data in a tree.

When the data cannot be found exactly, the search function might return the closest result, which might be a good starting point for adding a new node to the tree.

Depending on the tree structure, it is not necessarily guaranteed that the "closest" match is uniquely defined. This function will search for a node with the best match according to the sfunc (meaning: the return value of sfunc which is closest to zero). If that is also ambiguous, an arbitrary node matching the criteria is returned.

Parameters
rootthe root node
max_depththe maximum depth (zero=indefinite, one=just root)
datathe data to search for
sfuncthe search function
resultwhere the result shall be stored
loc_childrenoffset in the node struct for the children linked list
loc_nextoffset in the node struct for the next pointer
Returns
zero if the node was found exactly, positive if a node was found that could contain the node (but doesn't right now), negative if the tree does not contain any node that might be related to the searched data

◆ cx_tree_visitor()

CxTreeIterator cx_tree_visitor ( void * root,
ptrdiff_t loc_children,
ptrdiff_t loc_next )

Creates a breadth-first iterator for a tree with the specified root node.

Note
A tree visitor needs to maintain a queue of to-be visited nodes, which is allocated using the cxDefaultAllocator. When the visitor becomes invalid, this memory is automatically released. However, if you wish to cancel the iteration before the visitor becomes invalid by itself, you MUST call cxTreeIteratorDispose() manually to release the memory.
Remarks
The returned iterator does not support cxIteratorFlagRemoval().
Parameters
rootthe root node
loc_childrenoffset in the node struct for the children linked list
loc_nextoffset in the node struct for the next pointer
Returns
the new tree visitor
See also
cxTreeIteratorDispose()

◆ cxTreeAddData()

void * cxTreeAddData ( CxTree * tree,
void * parent,
const void * data )

Creates a new node and adds it to the tree.

Parameters
treethe tree
parentthe parent node of the new node
datathe data that will be submitted to the create function
Returns
the added node or NULL when the allocation failed
See also
cxTreeAdd()

◆ cxTreeAddNode()

void cxTreeAddNode ( CxTree * tree,
void * parent,
void * child )

Adds a new node to the tree.

If the child is already a member of the tree, the behavior is undefined. Use cxTreeSetParent() if you want to move a subtree to another location.

Attention
The node may be externally created, but MUST obey the same rules as if it was created by the tree itself with cxTreeAddData() (e.g., use the tree's allocator).
Parameters
treethe tree
parentthe parent of the node to add
childthe node to add
See also
cxTreeSetParent()
cxTreeAddData()

◆ cxTreeClear()

static void cxTreeClear ( CxTree * tree)
inlinestatic

Destroys the tree contents.

It is guaranteed that the simple destructor is invoked before the advanced destructor, starting with the leaf nodes of the subtree.

This is a convenience macro for invoking cxTreeDestroySubtree() on the root node of the tree.

Attention
Be careful when calling this function when no destructor function is registered that actually frees the memory of nodes. In that case you will need a reference to the (former) root node of the tree somewhere, or otherwise you will be leaking memory.
Parameters
treethe tree
See also
cxTreeDestroySubtree()

◆ cxTreeCreate()

CxTree * cxTreeCreate ( const CxAllocator * allocator,
size_t node_size,
size_t elem_size,
void * root,
ptrdiff_t loc_data,
ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
ptrdiff_t loc_prev,
ptrdiff_t loc_next )

Creates a new tree.

The specified allocator will be used for creating the tree struct and the nodes.

When you do not specify an existing root, the tree will be created empty. Additionally, cxFree() is registered as the advanced destructor for the tree so that all nodes that you will add to the tree are automatically freed together with the tree. When root is not NULL, no destructors are registered automatically.

Parameters
allocatorthe allocator to use (if NULL, the cxDefaultAllocator is assumed)
node_sizethe complete size of one node
elem_sizethe size of the payload stored in the node (CX_STORE_POINTERS is also supported)
rootan optional already existing root node
loc_dataoptional offset in the node struct for the payload (when negative, cxTreeAddData() is not supported)
loc_parentoffset in the node struct for the parent pointer
loc_childrenoffset in the node struct for the children linked list
loc_last_childoptional offset in the node struct for the pointer to the last child in the linked list (negative if there is no such pointer)
loc_prevoptional offset in the node struct for the prev pointer
loc_nextoffset in the node struct for the next pointer
Returns
the new tree
See also
cxTreeCreate()

◆ cxTreeCreateNode()

void * cxTreeCreateNode ( CxTree * tree,
void * parent )

Creates a new node and adds it to the tree.

Parameters
treethe tree
parentthe parent node of the new node
Returns
the added node or NULL when the allocation failed

◆ cxTreeCreateRoot()

void * cxTreeCreateRoot ( CxTree * tree)

Creates a new root node or returns the existing root node.

Parameters
treethe tree
Returns
the new root node, the existing root node, or NULL when the allocation failed
See also
cxTreeCreateRootData()

◆ cxTreeCreateRootData()

void * cxTreeCreateRootData ( CxTree * tree,
const void * data )

Creates a new root node or uses the existing root node and writes the specified data to that node.

Note
This function immediately returns NULL when loc_data was not initialized with a positive value.
Parameters
treethe tree
datathe data for the root node
Returns
the new root node, the existing root node, or NULL when the allocation failed or the data location is not known
See also
cxTreeCreateRoot()

◆ cxTreeDepth()

size_t cxTreeDepth ( CxTree * tree)

Determines the depth of the entire tree.

Parameters
treethe tree
Returns
the tree depth, counting the root as one

◆ cxTreeDestroyNode()

int cxTreeDestroyNode ( CxTree * tree,
void * node,
cx_tree_relink_func relink_func )

Destroys a node and re-links its children to its former parent.

If the node is not part of the tree, the behavior is undefined.

It is guaranteed that the simple destructor is invoked before the advanced destructor.

Attention
This function will not free the memory of the node with the tree's allocator, because that is usually done by the advanced destructor and would therefore result in a double-free.
Parameters
treethe tree
nodethe node to destroy (must not be the root node)
relink_funcoptional callback to update the content of each re-linked node
Returns
zero on success, non-zero if node is the root node of the tree

◆ cxTreeDestroySubtree()

void cxTreeDestroySubtree ( CxTree * tree,
void * node )

Destroys a node and its subtree.

It is guaranteed that the simple destructor is invoked before the advanced destructor, starting with the leaf nodes of the subtree.

When this function is invoked on the root node of the tree, it destroys the tree contents, but - in contrast to cxTreeFree() - not the tree structure, leaving an empty tree behind.

Note
The destructor function, if any, will not be invoked. That means you will need to free the removed subtree by yourself, eventually.
Attention
This function will not free the memory of the nodes with the tree's allocator, because that is usually done by the advanced destructor and would therefore result in a double-free.
Parameters
treethe tree
nodethe node being the root of the subtree to remove
See also
cxTreeFree()

◆ cxTreeFind()

static void * cxTreeFind ( CxTree * tree,
const void * data,
bool use_dfs )
inlinestatic

Searches the data in the specified tree.

Attention
When loc_data is not available, this function immediately returns NULL.
Parameters
treethe tree
datathe data to search for
use_dfstrue when depth-first search should be used; false when breadth-first search should be used
Returns
the first matching node, or NULL when the data cannot be found
See also
cxTreeFindInSubtree()
cxTreeFindFast()

◆ cxTreeFindFast()

static void * cxTreeFindFast ( CxTree * tree,
const void * data,
cx_tree_search_func sfunc )
inlinestatic

Performs an efficient depth-first search in the tree.

Parameters
treethe tree
datathe data to search for
sfuncthe search function
Returns
the first matching node, or NULL when the data cannot be found
See also
cxTreeFind()

◆ cxTreeFindFastInSubtree()

void * cxTreeFindFastInSubtree ( CxTree * tree,
const void * data,
cx_tree_search_func sfunc,
void * subtree_root,
size_t max_depth )

Performs an efficient depth-first search in a branch of the specified tree.

When max_depth is zero, the depth is not limited. The subtree_root itself is on depth 1 and its children have depth 2.

Note
When subtree_root is not NULL and not part of the tree, the behavior is undefined.
Parameters
treethe tree
datathe data to search for
sfuncthe search function
subtree_rootthe node where to start (NULL to start from root)
max_depththe maximum search depth
Returns
the first matching node, or NULL when the data cannot be found
See also
cxTreeFindInSubtree()

◆ cxTreeFindInSubtree()

void * cxTreeFindInSubtree ( CxTree * tree,
const void * data,
void * subtree_root,
size_t max_depth,
bool use_dfs )

Searches the data in the specified subtree.

When max_depth is zero, the depth is not limited. The subtree_root itself is on depth 1 and its children have depth 2.

Note
When subtree_root is not NULL and not part of the tree, the behavior is undefined.
Attention
When loc_data is not available, this function immediately returns NULL.
Parameters
treethe tree
datathe data to search for
subtree_rootthe node where to start (NULL to start from root)
max_depththe maximum search depth
use_dfstrue when depth-first search should be used; false when breadth-first search should be used
Returns
the first matching node, or NULL when the data cannot be found
See also
cxTreeFind()

◆ cxTreeFree()

void cxTreeFree ( CxTree * tree)

Deallocates the tree structure.

The destructor functions are invoked for each node, starting with the leaf nodes. It is guaranteed that for each node the simple destructor is invoked before the advanced destructor.

Attention
This function will only invoke the destructor functions on the nodes. It will NOT additionally free the nodes with the tree's allocator, because that would cause a double-free in most scenarios where the advanced destructor is already freeing the memory.
Parameters
treethe tree to free

◆ cxTreeIterate()

CxTreeIterator cxTreeIterate ( CxTree * tree,
bool visit_on_exit )

Creates a depth-first iterator for the specified tree.

Parameters
treethe tree to iterate
visit_on_exittrue, if the iterator shall visit a node again when leaving the subtree
Returns
a tree iterator (depth-first)
See also
cxTreeVisit()

◆ cxTreeIterateSubtree()

CxTreeIterator cxTreeIterateSubtree ( CxTree * tree,
void * node,
bool visit_on_exit )

Creates a depth-first iterator for the specified tree starting in node.

If the node is not part of the tree, the behavior is undefined.

Parameters
treethe tree to iterate
nodethe node where to start
visit_on_exittrue, if the iterator shall visit a node again when leaving the subtree
Returns
a tree iterator (depth-first)
See also
cxTreeVisit()

◆ cxTreeIteratorDispose()

void cxTreeIteratorDispose ( CxTreeIterator * iter)

Releases internal memory of the given tree iterator.

Parameters
iterthe iterator

◆ cxTreeRemoveNode()

int cxTreeRemoveNode ( CxTree * tree,
void * node,
cx_tree_relink_func relink_func )

Removes a node and re-links its children to its former parent.

If the node is not part of the tree, the behavior is undefined.

Note
The destructor function, if any, will not be invoked. That means you will need to free the removed node by yourself, eventually.
Parameters
treethe tree
nodethe node to remove (must not be the root node)
relink_funcoptional callback to update the content of each re-linked node
Returns
zero on success, non-zero if node is the root node of the tree

◆ cxTreeRemoveSubtree()

void cxTreeRemoveSubtree ( CxTree * tree,
void * node )

Removes a node and its subtree from the tree.

If the node is not part of the tree, the behavior is undefined.

Note
The destructor function, if any, will not be invoked. That means you will need to free the removed subtree by yourself, eventually.
Parameters
treethe tree
nodethe node to remove

◆ cxTreeSetParent()

void cxTreeSetParent ( CxTree * tree,
void * parent,
void * child )

Sets the (new) parent of the specified child.

If the child is not already a member of the tree, this function behaves as cxTreeAddNode().

Parameters
treethe tree
parentthe (new) parent of the child
childthe node to add
See also
cxTreeAddNode()

◆ cxTreeSetRoot()

void * cxTreeSetRoot ( CxTree * tree,
void * new_root )

Exchanges the root of the tree.

Attention
The old tree nodes might need to be deallocated by the caller. On the other hand, when the tree has destructors registered, keep in mind that they will be applied to the new tree. In particular, using cxTreeCreate() with a NULL root and setting the root with this function is not equivalent to creating the tree with a reference to an existing root because trees created without a root will have destructors registered.
Parameters
treethe tree
new_rootthe new root node
Returns
the old root node (or NULL when the tree was empty)

◆ cxTreeSize()

size_t cxTreeSize ( CxTree * tree)

Determines the size of the entire tree.

Parameters
treethe tree
Returns
the tree size, counting the root as one

◆ cxTreeSubtreeDepth()

size_t cxTreeSubtreeDepth ( CxTree * tree,
void * subtree_root )

Determines the depth of the specified subtree.

Parameters
treethe tree
subtree_rootthe root node of the subtree
Returns
the tree depth including the subtree_root

◆ cxTreeSubtreeSize()

size_t cxTreeSubtreeSize ( CxTree * tree,
void * subtree_root )

Determines the size of the specified subtree.

Parameters
treethe tree
subtree_rootthe root node of the subtree
Returns
the number of nodes in the specified subtree

◆ cxTreeVisit()

CxTreeIterator cxTreeVisit ( CxTree * tree)

Creates a breadth-first iterator for the specified tree.

Parameters
treethe tree to iterate
Returns
a tree visitor (a.k.a. breadth-first iterator)
See also
cxTreeIterate()

◆ cxTreeVisitSubtree()

CxTreeIterator cxTreeVisitSubtree ( CxTree * tree,
void * node )

Creates a breadth-first iterator for the specified tree starting in node.

If the node is not part of the tree, the behavior is undefined.

Parameters
treethe tree to iterate
nodethe node where to start
Returns
a tree visitor (a.k.a. breadth-first iterator)
See also
cxTreeIterate()