add breadth-first search function to find client nodes in a tree
This commit is contained in:
68
util.c
68
util.c
@ -50,9 +50,7 @@ void wm_nodearray_push(NodeArray *arr, TreeNode node)
|
|||||||
bool wm_nodearray_pop(NodeArray *arr, TreeNode *ret)
|
bool wm_nodearray_pop(NodeArray *arr, TreeNode *ret)
|
||||||
{
|
{
|
||||||
assert(arr);
|
assert(arr);
|
||||||
|
assert(ret);
|
||||||
if (!ret || !arr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (arr->size == 0)
|
if (arr->size == 0)
|
||||||
return false;
|
return false;
|
||||||
@ -62,6 +60,21 @@ bool wm_nodearray_pop(NodeArray *arr, TreeNode *ret)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wm_nodearray_pop_front(NodeArray *arr, TreeNode *ret)
|
||||||
|
{
|
||||||
|
assert(arr);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
if (arr->size == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*ret = arr->nodes[0];
|
||||||
|
arr->size--;
|
||||||
|
memcpy(arr->nodes, arr->nodes+1, arr->size * sizeof(TreeNode));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool wm_nodearray_remove(NodeArray *arr, size_t index)
|
bool wm_nodearray_remove(NodeArray *arr, size_t index)
|
||||||
{
|
{
|
||||||
assert(arr);
|
assert(arr);
|
||||||
@ -91,6 +104,55 @@ void wm_nodearray_free(NodeArray *arr)
|
|||||||
free(arr->nodes);
|
free(arr->nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// breadth-first search for finding client nodes in tree
|
||||||
|
ClientArray wm_nodearray_find_clients(TreeNode *root)
|
||||||
|
{
|
||||||
|
assert(root);
|
||||||
|
|
||||||
|
/* storing visited nodes in an array and searching is
|
||||||
|
not optimal, but this is not a performance-critical function. */
|
||||||
|
NodeArray visited = wm_nodearray_new();
|
||||||
|
wm_nodearray_push(&visited, *root);
|
||||||
|
|
||||||
|
NodeArray queue = wm_nodearray_new();
|
||||||
|
ClientArray clients = wm_clientarray_new();
|
||||||
|
|
||||||
|
wm_nodearray_push(&queue, *root);
|
||||||
|
|
||||||
|
while (queue.size > 0) {
|
||||||
|
TreeNode node;
|
||||||
|
|
||||||
|
if (!wm_nodearray_pop_front(&queue, &node))
|
||||||
|
goto ret;
|
||||||
|
|
||||||
|
if (node.type == NODE_CLIENT)
|
||||||
|
wm_clientarray_push(&clients, *node.client);
|
||||||
|
|
||||||
|
for (int i = 0; i < node.children.size; i++) {
|
||||||
|
TreeNode child_node = node.children.nodes[i];
|
||||||
|
bool _visited = false;
|
||||||
|
|
||||||
|
for (int j = 0; j < visited.size; j++) {
|
||||||
|
// this comparison may not work
|
||||||
|
if (visited.nodes[j].children.nodes == child_node.children.nodes) {
|
||||||
|
_visited = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_visited) {
|
||||||
|
wm_nodearray_push(&visited, child_node);
|
||||||
|
wm_nodearray_push(&queue, child_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret:
|
||||||
|
wm_nodearray_free(&visited);
|
||||||
|
wm_nodearray_free(&queue);
|
||||||
|
return clients;
|
||||||
|
}
|
||||||
|
|
||||||
ClientArray wm_clientarray_new()
|
ClientArray wm_clientarray_new()
|
||||||
{
|
{
|
||||||
ClientArray arr;
|
ClientArray arr;
|
||||||
|
2
util.h
2
util.h
@ -54,8 +54,10 @@ void wm_treenode_init(TreeNode *node, NodeType type, TreeNode *parent);
|
|||||||
NodeArray wm_nodearray_new();
|
NodeArray wm_nodearray_new();
|
||||||
void wm_nodearray_push(NodeArray *arr, TreeNode node);
|
void wm_nodearray_push(NodeArray *arr, TreeNode node);
|
||||||
bool wm_nodearray_pop(NodeArray *arr, TreeNode *ret);
|
bool wm_nodearray_pop(NodeArray *arr, TreeNode *ret);
|
||||||
|
bool wm_nodearray_pop_front(NodeArray *arr, TreeNode *ret);
|
||||||
bool wm_nodearray_remove(NodeArray *arr, size_t index);
|
bool wm_nodearray_remove(NodeArray *arr, size_t index);
|
||||||
void wm_nodearray_free(NodeArray *arr);
|
void wm_nodearray_free(NodeArray *arr);
|
||||||
|
ClientArray wm_nodearray_find_clients(TreeNode *root);
|
||||||
|
|
||||||
ClientArray wm_clientarray_new();
|
ClientArray wm_clientarray_new();
|
||||||
void wm_clientarray_push(ClientArray *arr, Client node);
|
void wm_clientarray_push(ClientArray *arr, Client node);
|
||||||
|
Reference in New Issue
Block a user