Add tree search test
Some checks failed
libakstdlib CI Build / cmake_build (push) Failing after 2m41s
Some checks failed
libakstdlib CI Build / cmake_build (push) Failing after 2m41s
This commit is contained in:
@@ -79,5 +79,9 @@ add_executable(test_linkedlist tests/test_linkedlist.c)
|
|||||||
target_link_libraries(test_linkedlist PRIVATE akstdlib)
|
target_link_libraries(test_linkedlist PRIVATE akstdlib)
|
||||||
add_test(NAME linkedlist COMMAND test_linkedlist)
|
add_test(NAME linkedlist COMMAND test_linkedlist)
|
||||||
|
|
||||||
|
add_executable(test_tree tests/test_tree.c)
|
||||||
|
target_link_libraries(test_tree PRIVATE akstdlib)
|
||||||
|
add_test(NAME tree COMMAND test_tree)
|
||||||
|
|
||||||
|
|
||||||
# pkgconfig
|
# pkgconfig
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ akerr_ErrorContext AKERR_NOIGNORE *aksl_realpath(const char *restrict path, char
|
|||||||
akerr_ErrorContext AKERR_NOIGNORE *aksl_strhash_djb2(char *str, size_t len, uint32_t *hashval);
|
akerr_ErrorContext AKERR_NOIGNORE *aksl_strhash_djb2(char *str, size_t len, uint32_t *hashval);
|
||||||
|
|
||||||
// Linked list functions
|
// Linked list functions
|
||||||
akerr_ErrorContext AKERR_NOIGNORE *aksl_list_push(aksl_ListNode *list, aksl_ListNode *obj);
|
akerr_ErrorContext AKERR_NOIGNORE *aksl_list_append(aksl_ListNode *list, aksl_ListNode *obj);
|
||||||
akerr_ErrorContext AKERR_NOIGNORE *aksl_list_pop(aksl_ListNode *node);
|
akerr_ErrorContext AKERR_NOIGNORE *aksl_list_pop(aksl_ListNode *node);
|
||||||
akerr_ErrorContext AKERR_NOIGNORE *aksl_list_iterate(aksl_ListNode *list, aksl_ListNodeIterator iter, void *data);
|
akerr_ErrorContext AKERR_NOIGNORE *aksl_list_iterate(aksl_ListNode *list, aksl_ListNodeIterator iter, void *data);
|
||||||
|
|
||||||
|
|||||||
71
src/stdlib.c
71
src/stdlib.c
@@ -266,39 +266,46 @@ akerr_ErrorContext AKERR_NOIGNORE *aksl_tree_iterate(
|
|||||||
if ( lfree == NULL ) {
|
if ( lfree == NULL ) {
|
||||||
lfree = &aksl_free;
|
lfree = &aksl_free;
|
||||||
}
|
}
|
||||||
switch ( searchmode ) {
|
ATTEMPT {
|
||||||
case AKSL_TREE_SEARCH_DFS_PREORDER:
|
switch ( searchmode ) {
|
||||||
PASS(e, iter(root, data));
|
case AKSL_TREE_SEARCH_DFS_PREORDER:
|
||||||
if ( root->left != NULL ) {
|
CATCH(e, iter(root, data));
|
||||||
PASS(e, aksl_tree_iterate(root->left, iter, lalloc, lfree, searchmode, data, NULL));
|
if ( root->left != NULL ) {
|
||||||
|
PASS(e, aksl_tree_iterate(root->left, iter, lalloc, lfree, searchmode, data, NULL));
|
||||||
|
}
|
||||||
|
if ( root-> right != NULL ) {
|
||||||
|
PASS(e, aksl_tree_iterate(root->right, iter, lalloc, lfree, searchmode, data, NULL));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AKSL_TREE_SEARCH_DFS_POSTORDER:
|
||||||
|
if ( root->left != NULL ) {
|
||||||
|
PASS(e, aksl_tree_iterate(root->left, iter, lalloc, lfree, searchmode, data, NULL));
|
||||||
|
}
|
||||||
|
if ( root-> right != NULL ) {
|
||||||
|
PASS(e, aksl_tree_iterate(root->right, iter, lalloc, lfree, searchmode, data, NULL));
|
||||||
|
}
|
||||||
|
CATCH(e, iter(root, data));
|
||||||
|
break;
|
||||||
|
case AKSL_TREE_SEARCH_DFS_INORDER:
|
||||||
|
if ( root->left != NULL ) {
|
||||||
|
PASS(e, aksl_tree_iterate(root->left, iter, lalloc, lfree, searchmode, data, NULL));
|
||||||
|
}
|
||||||
|
CATCH(e, iter(root, data));
|
||||||
|
if ( root-> right != NULL ) {
|
||||||
|
PASS(e, aksl_tree_iterate(root->right, iter, lalloc, lfree, searchmode, data, NULL));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AKSL_TREE_SEARCH_BFS:
|
||||||
|
case AKSL_TREE_SEARCH_BFS_RIGHT:
|
||||||
|
FAIL_RETURN(e, AKERR_NOT_IMPLEMENTED, "Searchmode %d", searchmode);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if ( root-> right != NULL ) {
|
} CLEANUP {
|
||||||
PASS(e, aksl_tree_iterate(root->right, iter, lalloc, lfree, searchmode, data, NULL));
|
} PROCESS(e) {
|
||||||
}
|
} HANDLE(e, AKERR_ITERATOR_BREAK) {
|
||||||
break;
|
// This is not an error condition, it's just telling us to stop early
|
||||||
case AKSL_TREE_SEARCH_DFS_POSTORDER:
|
SUCCEED_RETURN(e);
|
||||||
if ( root->left != NULL ) {
|
} FINISH(e, true);
|
||||||
PASS(e, aksl_tree_iterate(root->left, iter, lalloc, lfree, searchmode, data, NULL));
|
|
||||||
}
|
|
||||||
if ( root-> right != NULL ) {
|
|
||||||
PASS(e, aksl_tree_iterate(root->right, iter, lalloc, lfree, searchmode, data, NULL));
|
|
||||||
}
|
|
||||||
PASS(e, iter(root, data));
|
|
||||||
break;
|
|
||||||
case AKSL_TREE_SEARCH_DFS_INORDER:
|
|
||||||
if ( root->left != NULL ) {
|
|
||||||
PASS(e, aksl_tree_iterate(root->left, iter, lalloc, lfree, searchmode, data, NULL));
|
|
||||||
}
|
|
||||||
PASS(e, iter(root, data));
|
|
||||||
if ( root-> right != NULL ) {
|
|
||||||
PASS(e, aksl_tree_iterate(root->right, iter, lalloc, lfree, searchmode, data, NULL));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AKSL_TREE_SEARCH_BFS:
|
|
||||||
case AKSL_TREE_SEARCH_BFS_RIGHT:
|
|
||||||
FAIL_RETURN(e, AKERR_NOT_IMPLEMENTED, "Searchmode %d", searchmode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SUCCEED_RETURN(e);
|
SUCCEED_RETURN(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ int main(void)
|
|||||||
{
|
{
|
||||||
PREPARE_ERROR(e);
|
PREPARE_ERROR(e);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
int count = 0;
|
||||||
aksl_ListNode mylist;
|
aksl_ListNode mylist;
|
||||||
aksl_ListNode node1;
|
aksl_ListNode node1;
|
||||||
aksl_ListNode node2;
|
aksl_ListNode node2;
|
||||||
|
|||||||
96
tests/test_tree.c
Normal file
96
tests/test_tree.c
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <akstdlib.h>
|
||||||
|
|
||||||
|
#define MAX_LEAVES 7
|
||||||
|
|
||||||
|
typedef struct TreeSearchParams
|
||||||
|
{
|
||||||
|
void *value;
|
||||||
|
int steps;
|
||||||
|
aksl_TreeNode *node;
|
||||||
|
} TreeSearchParams;
|
||||||
|
|
||||||
|
// This iterator does nothing but print the node names it is visiting
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *myiter(aksl_TreeNode *node, void *data)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
TreeSearchParams *parms = NULL;
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
FAIL_ZERO_RETURN(e, node, AKERR_NULLPOINTER, "node");
|
||||||
|
FAIL_ZERO_RETURN(e, data, AKERR_NULLPOINTER, "data");
|
||||||
|
parms = (TreeSearchParams *)data;
|
||||||
|
parms->steps += 1;
|
||||||
|
if ( node->leaf == parms->value ) {
|
||||||
|
parms->node = node;
|
||||||
|
FAIL_RETURN(e, AKERR_ITERATOR_BREAK, "stop");
|
||||||
|
}
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
aksl_TreeNode tree[MAX_LEAVES];
|
||||||
|
TreeSearchParams parms = {
|
||||||
|
.value = (void *)17336,
|
||||||
|
.steps = 0,
|
||||||
|
.node = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
ATTEMPT {
|
||||||
|
memset((void *)&tree, 0x00, sizeof(aksl_TreeNode) * MAX_LEAVES);
|
||||||
|
/*
|
||||||
|
* Here we build a 3 level tree
|
||||||
|
*
|
||||||
|
* LEFT RIGHT
|
||||||
|
* TREE[0]
|
||||||
|
* +--------^^---------+
|
||||||
|
* | |
|
||||||
|
* TREE[1] TREE[2]
|
||||||
|
* +---^^---+ +---^^---+
|
||||||
|
* | | | |
|
||||||
|
*TREE[3] TREE[4] TREE[5] TREE[6]
|
||||||
|
*/
|
||||||
|
tree[0].left = &tree[1];
|
||||||
|
tree[0].right = &tree[2];
|
||||||
|
tree[1].left = &tree[3];
|
||||||
|
tree[1].right = &tree[4];
|
||||||
|
tree[2].left = &tree[5];
|
||||||
|
tree[2].right = &tree[6];
|
||||||
|
|
||||||
|
// Hide a value in tree[6]
|
||||||
|
tree[6].leaf = (void *)17336;
|
||||||
|
|
||||||
|
// Search for the value 17336 using DFS_PREORDER
|
||||||
|
CATCH(e, aksl_tree_iterate(&tree[0], &myiter, NULL, NULL, AKSL_TREE_SEARCH_DFS_PREORDER, &parms, NULL));
|
||||||
|
if ( parms.node != &tree[6] ) {
|
||||||
|
FAIL_BREAK(e, AKERR_API, "DFS_PREORDER_SEARCH didn't find the node");
|
||||||
|
}
|
||||||
|
if ( parms.steps != 7 ) {
|
||||||
|
FAIL_BREAK(e, AKERR_API, "DFS_PREORDER_SEARCH should've found the node in 7 steps, instead took %d", parms.steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for the value 17336 using DFS_INORDER
|
||||||
|
CATCH(e, aksl_tree_iterate(&tree[0], &myiter, NULL, NULL, AKSL_TREE_SEARCH_DFS_INORDER, &parms, NULL));
|
||||||
|
if ( parms.node != &tree[6] ) {
|
||||||
|
FAIL_BREAK(e, AKERR_API, "DFS_INORDER_SEARCH didn't find the node");
|
||||||
|
}
|
||||||
|
if ( parms.steps != 7 ) {
|
||||||
|
FAIL_BREAK(e, AKERR_API, "DFS_INORDER_SEARCH should've found the node in 7 steps, instead took %d", parms.steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for the value 17336 using DFS_PREORDER
|
||||||
|
CATCH(e, aksl_tree_iterate(&tree[0], &myiter, NULL, NULL, AKSL_TREE_SEARCH_DFS_POSTORDER, &parms, NULL));
|
||||||
|
if ( parms.node != &tree[6] ) {
|
||||||
|
FAIL_BREAK(e, AKERR_API, "DFS_POSTORDER_SEARCH didn't find the node");
|
||||||
|
}
|
||||||
|
if ( parms.steps != 7 ) {
|
||||||
|
FAIL_BREAK(e, AKERR_API, "DFS_POSTORDER_SEARCH should've found the node in 7 steps, instead took %d", parms.steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(e) {
|
||||||
|
} FINISH_NORETURN(e);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user