docs/Writerside/topics/tree.h.md

changeset 1424
563033aa998c
parent 1295
b00c6ae1441a
equal deleted inserted replaced
1423:9a72258446cd 1424:563033aa998c
1 # Tree 1 # Tree
2 2
3 UCX provides several low-level function for working with arbitrary tree structures, 3 UCX provides several low-level functions for working with arbitrary tree structures,
4 as well as some high-level functions for trees that induce a certain order on the data they store. 4 as well as some high-level functions for trees that induce a certain order on the data they store.
5 5
6 The following convenience macros allow you to declare and use simple tree structures. 6 The following convenience macros allow you to declare and use simple tree structures.
7 7
8 ```C 8 ```C
13 13
14 The `CX_TREE_NODE_BASE` macro declares four pointers of type `Type*`: 14 The `CX_TREE_NODE_BASE` macro declares four pointers of type `Type*`:
15 `parent`, `children`, `last_child`, `prev`, and `next`, 15 `parent`, `children`, `last_child`, `prev`, and `next`,
16 which must be placed as first member into your struct. 16 which must be placed as first member into your struct.
17 17
18 You can use it for example like this: 18 You can use it, for example, like this:
19 ```C 19 ```C
20 typedef struct my_tree_node_s { 20 typedef struct my_tree_node_s {
21 CX_TREE_NODE_BASE(struct my_tree_node_s); 21 CX_TREE_NODE_BASE(struct my_tree_node_s);
22 int value; 22 int value;
23 char *desc; 23 char *desc;
104 104
105 If your wrapped tree structure does not have a `last_child` or a `prev` pointer, 105 If your wrapped tree structure does not have a `last_child` or a `prev` pointer,
106 you may specify a negative location to indicate the missing pointer. 106 you may specify a negative location to indicate the missing pointer.
107 All other pointers are mandatory and a non-negative location is expected. 107 All other pointers are mandatory and a non-negative location is expected.
108 108
109 Note, that a wrapped tree by default has no create or search functions assigned. 109 Note that a wrapped tree by default has no create or search functions assigned.
110 Therefore, if you wish to use one of the functions below that needs those function pointers set, 110 Therefore, if you wish to use one of the functions below that needs those function pointers set,
111 you will have to set them manually by assigning to the respective fields in the `CxTree` structure. 111 you will have to set them manually by assigning to the respective fields in the `CxTree` structure.
112 112
113 ### Example for wrapping a libxml2 tree 113 ### Example for wrapping a libxml2 tree
114 114
302 The search proceeds as follows, starting with the `root` node: 302 The search proceeds as follows, starting with the `root` node:
303 303
304 1. The current node is compared with `data` / `node` using the `sfunc`. 304 1. The current node is compared with `data` / `node` using the `sfunc`.
305 2. If `sfunc` returns zero, a matching node has been found and the pointer to that node is stored at the location given by `result`. 305 2. If `sfunc` returns zero, a matching node has been found and the pointer to that node is stored at the location given by `result`.
306 3. If `sfunc` returns a negative number, the entire subtree is skipped. 306 3. If `sfunc` returns a negative number, the entire subtree is skipped.
307 4. If `sfunc` returns a positive number, the subtree is searched, unless the number is larger than the number of an already searched subtree. The best match will be stored at the location given by `result`. 307 4. If `sfunc` returns a positive number, the subtree is searched, unless the number is larger than the number of an already searched subtree. The best match will be stored at the location given by `result`.
308 5. The return value will be the return value of the `sfunc` for node that was stored in the `result`, or a negative number when no match was found 308 5. The return value will be the return value of the `sfunc` for node that was stored in the `result`, or a negative number when no match was found
309 309
310 > If the `sfunc` implements some kind of metric, the search functions will return the best match in the tree with respect to that metric. 310 > If the `sfunc` implements some kind of metric, the search functions will return the best match in the tree with respect to that metric.
311 > When a positive number is returned, it means, that a new node with the searched data could be added as a child of the found node. 311 > When a positive number is returned, it means that a new node with the searched data could be added as a child of the found node.
312 > This is exactly how `cx_tree_add()` finds the best position to add a node to the tree. 312 > This is exactly how `cx_tree_add()` finds the best position to add a node to the tree.
313 313
314 The function `cxTreeFind()` uses the `search_data_func` of the `CxTree` 314 The function `cxTreeFind()` uses the `search_data_func` of the `CxTree`
315 to find the `data` in the tree, and returns a pointer to the node when the data was found (or `NULL`, otherwise). 315 to find the `data` in the tree, and returns a pointer to the node when the data was found (or `NULL`, otherwise).
316 316
346 #define cxTreeVisitorContinue(visitor) 346 #define cxTreeVisitorContinue(visitor)
347 347
348 void cxTreeVisitorDispose(CxTreeVisitor *visitor); 348 void cxTreeVisitorDispose(CxTreeVisitor *visitor);
349 ``` 349 ```
350 350
351 There are two different kind of iterators for trees. 351 There are two different kinds of iterators for trees.
352 The `CxTreeIterator` is performing a depth-first iteration with the capability of visiting a node twice: 352 The `CxTreeIterator` is performing a depth-first iteration with the capability of visiting a node twice:
353 first when the iterator enters the node coming from its parent, and secondly when the iterator tracks back from its last child. 353 first when the iterator enters the node coming from its parent, and secondly when the iterator tracks back from its last child.
354 This behavior is controlled via the `visit_on_exit` argument. 354 This behavior is controlled via the `visit_on_exit` argument.
355 When set to `true`, the iterators `exiting` flag can be checked during iteration to see whether the iterator is currently entering or leaving the node. 355 When set to `true`, the iterators `exiting` flag can be checked during iteration to see whether the iterator is currently entering or leaving the node.
356 The above [example](#example-for-wrapping-a-libxml2-tree) for iterating through an XML tree illustrates this. 356 The above [example](#example-for-wrapping-a-libxml2-tree) for iterating through an XML tree illustrates this.
357 357
358 On the other hand, the `CxTreeVisitor` performs a breadth-first iteration and visits every node only once. 358 On the other hand, the `CxTreeVisitor` performs a breadth-first iteration and visits every node only once.
359 359
360 Since tree iteration needs to keep track of a stack (depth-first) or queue (breadth-frist), internal memory is allocated. 360 Since tree iteration needs to keep track of a stack (depth-first) or queue (breadth-first), internal memory is allocated.
361 This memory is _automatically_ disposed when the iteration _completes_. 361 This memory is _automatically_ disposed of when the iteration _completes_.
362 If you break from the iteration early, you must call `cxTreeIteratorDispose()` or `cxTreeVisitorDispose()`, respectively, to deallocate the memory. 362 If you break from the iteration early, you must call `cxTreeIteratorDispose()` or `cxTreeVisitorDispose()`, respectively, to deallocate the memory.
363 363
364 > It is recommended to always invoke the dispose functions, even when it seems not necessary. 364 > It is recommended to always invoke the dispose functions, even when it seems not necessary.
365 > In the best case it just does nothing, but calling them guarantees that no memory can be leaking, even when your code changes in the future. 365 > In the best case it just does nothing, but calling them guarantees that no memory can be leaking, even when your code will change in the future.
366 >{style="note"} 366 >{style="note"}
367 367
368 The macros `cxTreeIteratorContinue()` and `cxTreeVisitorContinue()` equivalently instruct the iterator/visitor to skip the subtree below the currently inspected node. 368 The macros `cxTreeIteratorContinue()` and `cxTreeVisitorContinue()` equivalently instruct the iterator/visitor to skip the subtree below the currently inspected node.
369 369
370 ## Remove 370 ## Remove
410 void cxTreeFree(CxTree *tree); 410 void cxTreeFree(CxTree *tree);
411 ``` 411 ```
412 412
413 The function `cxTreeDestroyNode()` first [removes](#remove) the `node` from the tree, like `cxTreeRemoveNode()`, 413 The function `cxTreeDestroyNode()` first [removes](#remove) the `node` from the tree, like `cxTreeRemoveNode()`,
414 and then invokes the [destructor functions](collection.h.md#destructor-functions). 414 and then invokes the [destructor functions](collection.h.md#destructor-functions).
415 It is guaranteed, that the simple destructor is called before the advanced destructor. 415 It is guaranteed that the simple destructor is called before the advanced destructor.
416 If no destructor function is registered at all, the behavior is identical to `cxTreeRemoveNode()`. 416 If no destructor function is registered at all, the behavior is identical to `cxTreeRemoveNode()`.
417 That means, this function does not deallocate the memory for the node on its own and leaves that entirely to the destructor functions. 417 That means this function does not deallocate the memory for the node on its own and leaves that entirely to the destructor functions.
418 418
419 The function `cxTreeDestroySubtree()` performs the above actions for the entire subtree starting with `node`. 419 The function `cxTreeDestroySubtree()` performs the above actions for the entire subtree starting with `node`.
420 The order in which the destructor functions for the nodes of the subtree are called are determined by a [tree iterator](#iterator-and-visitor). 420 The order in which the destructor functions for the nodes of the subtree are called is determined by a [tree iterator](#iterator-and-visitor).
421 421
422 The function `cxTreeClear()` is a shorthand for invoking `cxTreeDestroySubtree()` on the root node of the tree. 422 The function `cxTreeClear()` is a shorthand for invoking `cxTreeDestroySubtree()` on the root node of the tree.
423 423
424 The function `cxTreeFree()` behaves like `cxTreeClear()` and then deallocates the memory for the `CxTree` structure. 424 The function `cxTreeFree()` behaves like `cxTreeClear()` and then deallocates the memory for the `CxTree` structure.
425 425

mercurial