add breadth-first search function to find client nodes in a tree
This commit is contained in:
parent
92a5dc5cf1
commit
c5990665f5
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)
|
||||
{
|
||||
assert(arr);
|
||||
|
||||
if (!ret || !arr)
|
||||
return false;
|
||||
assert(ret);
|
||||
|
||||
if (arr->size == 0)
|
||||
return false;
|
||||
@ -62,6 +60,21 @@ bool wm_nodearray_pop(NodeArray *arr, TreeNode *ret)
|
||||
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)
|
||||
{
|
||||
assert(arr);
|
||||
@ -91,6 +104,55 @@ void wm_nodearray_free(NodeArray *arr)
|
||||
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 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();
|
||||
void wm_nodearray_push(NodeArray *arr, TreeNode node);
|
||||
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);
|
||||
void wm_nodearray_free(NodeArray *arr);
|
||||
ClientArray wm_nodearray_find_clients(TreeNode *root);
|
||||
|
||||
ClientArray wm_clientarray_new();
|
||||
void wm_clientarray_push(ClientArray *arr, Client node);
|
||||
|
Loading…
x
Reference in New Issue
Block a user