From ff3a1a6884a30e180fac90ac2128c29f26f94514 Mon Sep 17 00:00:00 2001 From: David Avdat Date: Mon, 8 Apr 2019 11:28:20 +0300 Subject: [PATCH 1/2] adding preorder traversal --- avl_tree.c | 32 ++++++++++++++++++++++++++++++++ avl_tree.h | 38 ++++++++++++++++++++++++++++++-------- test.c | 15 +++++++++++++++ 3 files changed, 77 insertions(+), 8 deletions(-) diff --git a/avl_tree.c b/avl_tree.c index 4fdff6f..5fb8266 100644 --- a/avl_tree.c +++ b/avl_tree.c @@ -93,6 +93,37 @@ avl_tree_prev_in_order(const struct avl_tree_node *node) return avl_tree_next_or_prev_in_order(node, -1); } +/* Starts a preorder traversal of the tree. */ +struct avl_tree_node * +avl_tree_first_in_preorder(const struct avl_tree_node *root) +{ + return (struct avl_tree_node *)root; +} + +/* Continues a preorder traversal of the tree. @prev_parent must be its saved + * parent node. Returns NULL if there are no more nodes (i.e. @prev was the + * root of the tree). */ +struct avl_tree_node * +avl_tree_next_in_preorder(const struct avl_tree_node *prev, + const struct avl_tree_node *prev_parent) +{ + const struct avl_tree_node *next = NULL; + + if (prev && (prev->left || prev->right)) + next = prev->left ? prev->left : prev->right; + else + for (; + prev_parent; + prev = prev_parent, prev_parent = avl_get_parent(prev_parent)) + if (prev_parent->right && prev_parent->right != prev) + { + next = prev_parent->right; + break; + } + + return (struct avl_tree_node *)next; +} + /* Starts a postorder traversal of the tree. */ struct avl_tree_node * avl_tree_first_in_postorder(const struct avl_tree_node *root) @@ -787,3 +818,4 @@ avl_tree_remove(struct avl_tree_node **root_ptr, struct avl_tree_node *node) -1, &left_deleted); } while (parent); } + diff --git a/avl_tree.h b/avl_tree.h index 0dc6b4e..ef01cc6 100644 --- a/avl_tree.h +++ b/avl_tree.h @@ -285,6 +285,13 @@ avl_tree_next_in_order(const struct avl_tree_node *node); extern struct avl_tree_node * avl_tree_prev_in_order(const struct avl_tree_node *node); +extern struct avl_tree_node * +avl_tree_first_in_preorder(const struct avl_tree_node *root); + +extern struct avl_tree_node * +avl_tree_next_in_preorder(const struct avl_tree_node *prev, + const struct avl_tree_node *prev_parent); + extern struct avl_tree_node * avl_tree_first_in_postorder(const struct avl_tree_node *root); @@ -342,18 +349,33 @@ avl_tree_next_in_postorder(const struct avl_tree_node *prev, struct_member), 1); \ _cur = avl_tree_prev_in_order(_cur)) -/* - * Like avl_tree_for_each_in_order(), but iterates through the nodes in - * postorder, so the current node may be deleted or freed. - */ -#define avl_tree_for_each_in_postorder(child_struct, root, \ - struct_name, struct_member) \ + +#define avl_tree_for_each(child_struct, root, \ + struct_name, struct_member, order) \ for (struct avl_tree_node *_cur = \ - avl_tree_first_in_postorder(root), *_parent; \ + avl_tree_first_in_##order(root), *_parent; \ _cur && ((child_struct) = \ avl_tree_entry(_cur, struct_name, \ struct_member), 1) \ && (_parent = avl_get_parent(_cur), 1); \ - _cur = avl_tree_next_in_postorder(_cur, _parent)) + _cur = avl_tree_next_in_##order(_cur, _parent)) + +/* + * Like avl_tree_for_each_in_order(), but iterates through the nodes in + * preorder. + */ +#define avl_tree_for_each_in_preorder(child_struct, root, \ + struct_name, struct_member) \ + avl_tree_for_each(child_struct, root, \ + struct_name, struct_member, preorder) + +/* + * Like avl_tree_for_each_in_order(), but iterates through the nodes in + * postorder, so the current node may be deleted or freed. + */ +#define avl_tree_for_each_in_postorder(child_struct, root, \ + struct_name, struct_member) \ + avl_tree_for_each(child_struct, root, \ + struct_name, struct_member, postorder) #endif /* _AVL_TREE_H_ */ diff --git a/test.c b/test.c index 55c6bdb..59b7104 100644 --- a/test.c +++ b/test.c @@ -179,6 +179,20 @@ verify(const int *data, int count) } assert(x == -1); + /* Check preorder traversal. */ + for (cur = avl_tree_first_in_preorder(root), x = 0; + cur; + cur = avl_tree_next_in_preorder(cur, avl_get_parent(cur)), x++) + { + assert(TEST_NODE(cur)->reached); + TEST_NODE(cur)->reached = 0; + assert(!avl_get_parent(cur) || + !(TEST_NODE(avl_get_parent(cur))->reached)); + assert(!cur->left || TEST_NODE(cur->left)->reached); + assert(!cur->right || TEST_NODE(cur->right)->reached); + } + + assert(x == count); /* Check postorder traversal. */ for (cur = avl_tree_first_in_postorder(root), x = 0; cur; @@ -192,6 +206,7 @@ verify(const int *data, int count) assert(!cur->right || TEST_NODE(cur->right)->reached); } assert(x == count); + } #endif From a06901e2b7b31873fd4e8c8ad56e1bcc16e532f3 Mon Sep 17 00:00:00 2001 From: David Avdat Date: Mon, 8 Apr 2019 11:37:58 +0300 Subject: [PATCH 2/2] adding preorder traversal --- avl_tree.c | 62 +++++++++++++++++++++++++++--------------------------- avl_tree.h | 16 +++++++------- test.c | 27 ++++++++++++------------ 3 files changed, 52 insertions(+), 53 deletions(-) diff --git a/avl_tree.c b/avl_tree.c index 5fb8266..e5b911d 100644 --- a/avl_tree.c +++ b/avl_tree.c @@ -93,37 +93,6 @@ avl_tree_prev_in_order(const struct avl_tree_node *node) return avl_tree_next_or_prev_in_order(node, -1); } -/* Starts a preorder traversal of the tree. */ -struct avl_tree_node * -avl_tree_first_in_preorder(const struct avl_tree_node *root) -{ - return (struct avl_tree_node *)root; -} - -/* Continues a preorder traversal of the tree. @prev_parent must be its saved - * parent node. Returns NULL if there are no more nodes (i.e. @prev was the - * root of the tree). */ -struct avl_tree_node * -avl_tree_next_in_preorder(const struct avl_tree_node *prev, - const struct avl_tree_node *prev_parent) -{ - const struct avl_tree_node *next = NULL; - - if (prev && (prev->left || prev->right)) - next = prev->left ? prev->left : prev->right; - else - for (; - prev_parent; - prev = prev_parent, prev_parent = avl_get_parent(prev_parent)) - if (prev_parent->right && prev_parent->right != prev) - { - next = prev_parent->right; - break; - } - - return (struct avl_tree_node *)next; -} - /* Starts a postorder traversal of the tree. */ struct avl_tree_node * avl_tree_first_in_postorder(const struct avl_tree_node *root) @@ -819,3 +788,34 @@ avl_tree_remove(struct avl_tree_node **root_ptr, struct avl_tree_node *node) } while (parent); } +/* Starts a preorder traversal of the tree. */ +struct avl_tree_node * +avl_tree_first_in_preorder(const struct avl_tree_node *root) +{ + return (struct avl_tree_node *)root; +} + +/* Continues a preorder traversal of the tree. @prev_parent must be its saved + * parent node. Returns NULL if there are no more nodes (i.e. @prev was the + * root of the tree). */ +struct avl_tree_node * +avl_tree_next_in_preorder(const struct avl_tree_node *prev, + const struct avl_tree_node *prev_parent) +{ + const struct avl_tree_node *next = NULL; + + if (prev && (prev->left || prev->right)) + next = prev->left ? prev->left : prev->right; + else + for (; + prev_parent; + prev = prev_parent, prev_parent = avl_get_parent(prev_parent)) + if (prev_parent->right && prev_parent->right != prev) + { + next = prev_parent->right; + break; + } + + return (struct avl_tree_node *)next; +} + diff --git a/avl_tree.h b/avl_tree.h index ef01cc6..8b84c43 100644 --- a/avl_tree.h +++ b/avl_tree.h @@ -362,20 +362,20 @@ avl_tree_next_in_postorder(const struct avl_tree_node *prev, /* * Like avl_tree_for_each_in_order(), but iterates through the nodes in - * preorder. + * postorder, so the current node may be deleted or freed. */ -#define avl_tree_for_each_in_preorder(child_struct, root, \ - struct_name, struct_member) \ +#define avl_tree_for_each_in_postorder(child_struct, root, \ + struct_name, struct_member) \ avl_tree_for_each(child_struct, root, \ - struct_name, struct_member, preorder) + struct_name, struct_member, postorder) /* * Like avl_tree_for_each_in_order(), but iterates through the nodes in - * postorder, so the current node may be deleted or freed. + * preorder. */ -#define avl_tree_for_each_in_postorder(child_struct, root, \ - struct_name, struct_member) \ +#define avl_tree_for_each_in_preorder(child_struct, root, \ + struct_name, struct_member) \ avl_tree_for_each(child_struct, root, \ - struct_name, struct_member, postorder) + struct_name, struct_member, preorder) #endif /* _AVL_TREE_H_ */ diff --git a/test.c b/test.c index 59b7104..82ce44e 100644 --- a/test.c +++ b/test.c @@ -179,20 +179,6 @@ verify(const int *data, int count) } assert(x == -1); - /* Check preorder traversal. */ - for (cur = avl_tree_first_in_preorder(root), x = 0; - cur; - cur = avl_tree_next_in_preorder(cur, avl_get_parent(cur)), x++) - { - assert(TEST_NODE(cur)->reached); - TEST_NODE(cur)->reached = 0; - assert(!avl_get_parent(cur) || - !(TEST_NODE(avl_get_parent(cur))->reached)); - assert(!cur->left || TEST_NODE(cur->left)->reached); - assert(!cur->right || TEST_NODE(cur->right)->reached); - } - - assert(x == count); /* Check postorder traversal. */ for (cur = avl_tree_first_in_postorder(root), x = 0; cur; @@ -207,6 +193,19 @@ verify(const int *data, int count) } assert(x == count); + /* Check preorder traversal. */ + for (cur = avl_tree_first_in_preorder(root), x = 0; + cur; + cur = avl_tree_next_in_preorder(cur, avl_get_parent(cur)), x++) + { + assert(TEST_NODE(cur)->reached); + TEST_NODE(cur)->reached = 0; + assert(!avl_get_parent(cur) || + !(TEST_NODE(avl_get_parent(cur))->reached)); + assert(!cur->left || TEST_NODE(cur->left)->reached); + assert(!cur->right || TEST_NODE(cur->right)->reached); + } + assert(x == count); } #endif