ucx/tree.c

changeset 888
af685cc9d623
parent 854
1c8401ece69e
equal deleted inserted replaced
877:b60487c3ec36 888:af685cc9d623
224 cx_foreach(void *, elem, iter) { 224 cx_foreach(void *, elem, iter) {
225 // investigate the current node 225 // investigate the current node
226 int ret_elem = sfunc(elem, node); 226 int ret_elem = sfunc(elem, node);
227 if (ret_elem == 0) { 227 if (ret_elem == 0) {
228 // if found, exit the search 228 // if found, exit the search
229 *result = (void *) elem; 229 *result = elem;
230 ret = 0; 230 ret = 0;
231 break; 231 break;
232 } else if (ret_elem > 0 && ret_elem < ret) { 232 } else if (ret_elem > 0 && ret_elem < ret) {
233 // new distance is better 233 // new distance is better
234 *result = elem; 234 *result = elem;
235 ret = ret_elem; 235 ret = ret_elem;
236 } else { 236 } else if (ret_elem < 0 || ret_elem > ret) {
237 // not contained or distance is worse, skip entire subtree 237 // not contained or distance is worse, skip entire subtree
238 cxTreeIteratorContinue(iter); 238 cxTreeIteratorContinue(iter);
239 } 239 }
240 240
241 // when we reached the max depth, skip the subtree 241 // when we reached the max depth, skip the subtree
303 } 303 }
304 } 304 }
305 305
306 if (children == NULL) { 306 if (children == NULL) {
307 // search for the next node 307 // search for the next node
308 void *next; 308 void *next = NULL;
309 cx_tree_iter_search_next: 309 cx_tree_iter_search_next:
310 // check if there is a sibling 310 // check if there is a sibling, but only if we are not a (subtree-)root
311 if (iter->exiting) { 311 if (iter->exiting) {
312 next = iter->node_next; 312 next = iter->node_next;
313 } else { 313 } else if (iter->depth > 1) {
314 next = tree_next(iter->node); 314 next = tree_next(iter->node);
315 iter->node_next = next; 315 iter->node_next = next;
316 } 316 }
317 if (next == NULL) { 317 if (next == NULL) {
318 // no sibling, we are done with this node and exit 318 // no sibling, we are done with this node and exit
324 if (iter->depth == 1) { 324 if (iter->depth == 1) {
325 // there is no parent - we have iterated the entire tree 325 // there is no parent - we have iterated the entire tree
326 // invalidate the iterator and free the node stack 326 // invalidate the iterator and free the node stack
327 iter->node = iter->node_next = NULL; 327 iter->node = iter->node_next = NULL;
328 iter->stack_capacity = iter->depth = 0; 328 iter->stack_capacity = iter->depth = 0;
329 free(iter->stack); 329 cxFreeDefault(iter->stack);
330 iter->stack = NULL; 330 iter->stack = NULL;
331 } else { 331 } else {
332 // the parent node can be obtained from the top of stack 332 // the parent node can be obtained from the top of stack
333 // this way we can avoid the loc_parent in the iterator 333 // this way we can avoid the loc_parent in the iterator
334 iter->depth--; 334 iter->depth--;
373 iter.node_next = NULL; 373 iter.node_next = NULL;
374 iter.exiting = false; 374 iter.exiting = false;
375 iter.skip = false; 375 iter.skip = false;
376 376
377 // assign base iterator functions 377 // assign base iterator functions
378 iter.base.mutating = false; 378 iter.base.allow_remove = false;
379 iter.base.remove = false; 379 iter.base.remove = false;
380 iter.base.current_impl = NULL; 380 iter.base.current_impl = NULL;
381 iter.base.valid = cx_tree_iter_valid; 381 iter.base.valid = cx_tree_iter_valid;
382 iter.base.next = cx_tree_iter_next; 382 iter.base.next = cx_tree_iter_next;
383 iter.base.current = cx_tree_iter_current; 383 iter.base.current = cx_tree_iter_current;
384 384
385 // visit the root node 385 // visit the root node
386 iter.node = root; 386 iter.node = root;
387 if (root != NULL) { 387 if (root != NULL) {
388 iter.stack_capacity = 16; 388 iter.stack_capacity = 16;
389 iter.stack = malloc(sizeof(void *) * 16); 389 iter.stack = cxMallocDefault(sizeof(void *) * 16);
390 iter.stack[0] = root; 390 iter.stack[0] = root;
391 iter.counter = 1; 391 iter.counter = 1;
392 iter.depth = 1; 392 iter.depth = 1;
393 } else { 393 } else {
394 iter.stack_capacity = 0; 394 iter.stack_capacity = 0;
414 static void cx_tree_visitor_enqueue_siblings( 414 static void cx_tree_visitor_enqueue_siblings(
415 struct cx_tree_visitor_s *iter, void *node, ptrdiff_t loc_next) { 415 struct cx_tree_visitor_s *iter, void *node, ptrdiff_t loc_next) {
416 node = tree_next(node); 416 node = tree_next(node);
417 while (node != NULL) { 417 while (node != NULL) {
418 struct cx_tree_visitor_queue_s *q; 418 struct cx_tree_visitor_queue_s *q;
419 q = malloc(sizeof(struct cx_tree_visitor_queue_s)); 419 q = cxMallocDefault(sizeof(struct cx_tree_visitor_queue_s));
420 q->depth = iter->queue_last->depth; 420 q->depth = iter->queue_last->depth;
421 q->node = node; 421 q->node = node;
422 iter->queue_last->next = q; 422 iter->queue_last->next = q;
423 iter->queue_last = q; 423 iter->queue_last = q;
424 node = tree_next(node); 424 node = tree_next(node);
443 } else { 443 } else {
444 children = tree_children(iter->node); 444 children = tree_children(iter->node);
445 } 445 }
446 if (children != NULL) { 446 if (children != NULL) {
447 struct cx_tree_visitor_queue_s *q; 447 struct cx_tree_visitor_queue_s *q;
448 q = malloc(sizeof(struct cx_tree_visitor_queue_s)); 448 q = cxMallocDefault(sizeof(struct cx_tree_visitor_queue_s));
449 q->depth = iter->depth + 1; 449 q->depth = iter->depth + 1;
450 q->node = children; 450 q->node = children;
451 if (iter->queue_last == NULL) { 451 if (iter->queue_last == NULL) {
452 assert(iter->queue_next == NULL); 452 assert(iter->queue_next == NULL);
453 iter->queue_next = q; 453 iter->queue_next = q;
472 iter->queue_next = q->next; 472 iter->queue_next = q->next;
473 if (iter->queue_next == NULL) { 473 if (iter->queue_next == NULL) {
474 assert(iter->queue_last == q); 474 assert(iter->queue_last == q);
475 iter->queue_last = NULL; 475 iter->queue_last = NULL;
476 } 476 }
477 free(q); 477 cxFreeDefault(q);
478 } 478 }
479 479
480 // increment the node counter 480 // increment the node counter
481 iter->counter++; 481 iter->counter++;
482 } 482 }
494 iter.skip = false; 494 iter.skip = false;
495 iter.queue_next = NULL; 495 iter.queue_next = NULL;
496 iter.queue_last = NULL; 496 iter.queue_last = NULL;
497 497
498 // assign base iterator functions 498 // assign base iterator functions
499 iter.base.mutating = false; 499 iter.base.allow_remove = false;
500 iter.base.remove = false; 500 iter.base.remove = false;
501 iter.base.current_impl = NULL; 501 iter.base.current_impl = NULL;
502 iter.base.valid = cx_tree_visitor_valid; 502 iter.base.valid = cx_tree_visitor_valid;
503 iter.base.next = cx_tree_visitor_next; 503 iter.base.next = cx_tree_visitor_next;
504 iter.base.current = cx_tree_visitor_current; 504 iter.base.current = cx_tree_visitor_current;
715 return 0; 715 return 0;
716 } 716 }
717 } 717 }
718 718
719 // otherwise, create iterator and hand over to other function 719 // otherwise, create iterator and hand over to other function
720 CxIterator iter = cxIterator(src, elem_size, num); 720 CxIterator iter = cxIterator(src, elem_size, num, false);
721 return cx_tree_add_iter(cxIteratorRef(iter), num, sfunc, 721 return cx_tree_add_iter(cxIteratorRef(iter), num, sfunc,
722 cfunc, cdata, failed, root, 722 cfunc, cdata, failed, root,
723 loc_parent, loc_children, loc_last_child, 723 loc_parent, loc_children, loc_last_child,
724 loc_prev, loc_next); 724 loc_prev, loc_next);
725 } 725 }
802 cx_tree_default_insert_element, 802 cx_tree_default_insert_element,
803 cx_tree_default_insert_many, 803 cx_tree_default_insert_many,
804 cx_tree_default_find 804 cx_tree_default_find
805 }; 805 };
806 806
807 CxTree *cxTreeCreate( 807 CxTree *cxTreeCreate(const CxAllocator *allocator,
808 const CxAllocator *allocator,
809 cx_tree_node_create_func create_func, 808 cx_tree_node_create_func create_func,
810 cx_tree_search_func search_func, 809 cx_tree_search_func search_func,
811 cx_tree_search_data_func search_data_func, 810 cx_tree_search_data_func search_data_func,
812 ptrdiff_t loc_parent, 811 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child,
813 ptrdiff_t loc_children, 812 ptrdiff_t loc_prev, ptrdiff_t loc_next
814 ptrdiff_t loc_last_child,
815 ptrdiff_t loc_prev,
816 ptrdiff_t loc_next
817 ) { 813 ) {
818 if (allocator == NULL) { 814 if (allocator == NULL) {
819 allocator = cxDefaultAllocator; 815 allocator = cxDefaultAllocator;
820 } 816 }
821 assert(create_func != NULL); 817 assert(create_func != NULL);
850 cxTreeClear(tree); 846 cxTreeClear(tree);
851 } 847 }
852 cxFree(tree->allocator, tree); 848 cxFree(tree->allocator, tree);
853 } 849 }
854 850
855 CxTree *cxTreeCreateWrapped( 851 CxTree *cxTreeCreateWrapped(const CxAllocator *allocator, void *root,
856 const CxAllocator *allocator, 852 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child,
857 void *root, 853 ptrdiff_t loc_prev, ptrdiff_t loc_next) {
858 ptrdiff_t loc_parent,
859 ptrdiff_t loc_children,
860 ptrdiff_t loc_last_child,
861 ptrdiff_t loc_prev,
862 ptrdiff_t loc_next
863 ) {
864 if (allocator == NULL) { 854 if (allocator == NULL) {
865 allocator = cxDefaultAllocator; 855 allocator = cxDefaultAllocator;
866 } 856 }
867 assert(root != NULL); 857 assert(root != NULL);
868 858
886 tree->root = root; 876 tree->root = root;
887 tree->size = cxTreeSubtreeSize(tree, root); 877 tree->size = cxTreeSubtreeSize(tree, root);
888 return tree; 878 return tree;
889 } 879 }
890 880
891 void cxTreeSetParent( 881 void cxTreeSetParent(CxTree *tree, void *parent, void *child) {
892 CxTree *tree,
893 void *parent,
894 void *child
895 ) {
896 size_t loc_parent = tree->loc_parent; 882 size_t loc_parent = tree->loc_parent;
897 if (tree_parent(child) == NULL) { 883 if (tree_parent(child) == NULL) {
898 tree->size++; 884 tree->size++;
899 } 885 }
900 cx_tree_link(parent, child, cx_tree_node_layout(tree)); 886 cx_tree_link(parent, child, cx_tree_node_layout(tree));
901 } 887 }
902 888
903 void cxTreeAddChildNode( 889 void cxTreeAddChildNode(CxTree *tree, void *parent, void *child) {
904 CxTree *tree,
905 void *parent,
906 void *child
907 ) {
908 cx_tree_link(parent, child, cx_tree_node_layout(tree)); 890 cx_tree_link(parent, child, cx_tree_node_layout(tree));
909 tree->size++; 891 tree->size++;
910 } 892 }
911 893
912 int cxTreeAddChild( 894 int cxTreeAddChild(CxTree *tree, void *parent, const void *data) {
913 CxTree *tree,
914 void *parent,
915 const void *data) {
916 void *node = tree->node_create(data, tree); 895 void *node = tree->node_create(data, tree);
917 if (node == NULL) return 1; 896 if (node == NULL) return 1;
918 cx_tree_zero_pointers(node, cx_tree_node_layout(tree)); 897 cx_tree_zero_pointers(node, cx_tree_node_layout(tree));
919 cx_tree_link(parent, node, cx_tree_node_layout(tree)); 898 cx_tree_link(parent, node, cx_tree_node_layout(tree));
920 tree->size++; 899 tree->size++;
921 return 0; 900 return 0;
901 }
902
903 int cxTreeInsert(CxTree *tree, const void *data) {
904 return tree->cl->insert_element(tree, data);
905 }
906
907 size_t cxTreeInsertIter(CxTree *tree, CxIteratorBase *iter, size_t n) {
908 return tree->cl->insert_many(tree, iter, n);
909 }
910
911 size_t cxTreeInsertArray(CxTree *tree, const void *data, size_t elem_size, size_t n) {
912 if (n == 0) return 0;
913 if (n == 1) return 0 == cxTreeInsert(tree, data) ? 1 : 0;
914 CxIterator iter = cxIterator(data, elem_size, n, false);
915 return cxTreeInsertIter(tree, cxIteratorRef(iter), n);
916 }
917
918 void *cxTreeFind( CxTree *tree, const void *data) {
919 return tree->cl->find(tree, tree->root, data, 0);
920 }
921
922 void *cxTreeFindInSubtree(CxTree *tree, const void *data, void *subtree_root, size_t max_depth) {
923 return tree->cl->find(tree, subtree_root, data, max_depth);
922 } 924 }
923 925
924 size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root) { 926 size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root) {
925 CxTreeVisitor visitor = cx_tree_visitor( 927 CxTreeVisitor visitor = cx_tree_visitor(
926 subtree_root, 928 subtree_root,
941 ); 943 );
942 while (cxIteratorValid(visitor)) { 944 while (cxIteratorValid(visitor)) {
943 cxIteratorNext(visitor); 945 cxIteratorNext(visitor);
944 } 946 }
945 return visitor.depth; 947 return visitor.depth;
948 }
949
950 size_t cxTreeSize(CxTree *tree) {
951 return tree->size;
946 } 952 }
947 953
948 size_t cxTreeDepth(CxTree *tree) { 954 size_t cxTreeDepth(CxTree *tree) {
949 CxTreeVisitor visitor = cx_tree_visitor( 955 CxTreeVisitor visitor = cx_tree_visitor(
950 tree->root, tree->loc_children, tree->loc_next 956 tree->root, tree->loc_children, tree->loc_next
1050 tree->size -= iter.counter; 1056 tree->size -= iter.counter;
1051 if (node == tree->root) { 1057 if (node == tree->root) {
1052 tree->root = NULL; 1058 tree->root = NULL;
1053 } 1059 }
1054 } 1060 }
1061
1062 void cxTreeIteratorDispose(CxTreeIterator *iter) {
1063 cxFreeDefault(iter->stack);
1064 iter->stack = NULL;
1065 }
1066
1067 void cxTreeVisitorDispose(CxTreeVisitor *visitor) {
1068 struct cx_tree_visitor_queue_s *q = visitor->queue_next;
1069 while (q != NULL) {
1070 struct cx_tree_visitor_queue_s *next = q->next;
1071 cxFreeDefault(q);
1072 q = next;
1073 }
1074 }
1075
1076 CxTreeIterator cxTreeIterateSubtree(CxTree *tree, void *node, bool visit_on_exit) {
1077 return cx_tree_iterator(
1078 node, visit_on_exit,
1079 tree->loc_children, tree->loc_next
1080 );
1081 }
1082
1083 CxTreeVisitor cxTreeVisitSubtree(CxTree *tree, void *node) {
1084 return cx_tree_visitor(
1085 node, tree->loc_children, tree->loc_next
1086 );
1087 }
1088
1089 CxTreeIterator cxTreeIterate(CxTree *tree, bool visit_on_exit) {
1090 return cxTreeIterateSubtree(tree, tree->root, visit_on_exit);
1091 }
1092
1093 CxTreeVisitor cxTreeVisit(CxTree *tree) {
1094 return cxTreeVisitSubtree(tree, tree->root);
1095 }

mercurial