implement tree edit distance utility functions
This commit is contained in:
parent
557a43e265
commit
a0f2f48ef2
92
src/util.c
92
src/util.c
@ -221,6 +221,98 @@ void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile)
|
||||
wm_ptrarray_free(&ws_str);
|
||||
}
|
||||
|
||||
TreeNode* wm_treenode_lmd(TreeNode *node)
|
||||
{
|
||||
assert(node);
|
||||
|
||||
if (node->children.size == 0) return node;
|
||||
|
||||
return wm_treenode_lmd(node->children.nodes[0]);
|
||||
}
|
||||
|
||||
PtrArray wm_treenode_all_lmds(TreeNode *node)
|
||||
{
|
||||
assert(node);
|
||||
|
||||
PtrArray postorder = wm_postorder_traversal(node);
|
||||
PtrArray ret = wm_ptrarray_new();
|
||||
|
||||
for (size_t i = 0; i < postorder.size; i++) {
|
||||
TreeNode *lmd = wm_treenode_lmd(postorder.ptrs[i]);
|
||||
|
||||
wm_ptrarray_push(&ret, (void*)lmd);
|
||||
}
|
||||
|
||||
wm_ptrarray_free(&postorder);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PtrArray wm_postorder_traversal(TreeNode *tree)
|
||||
{
|
||||
assert(tree);
|
||||
|
||||
TreeNode *root = tree;
|
||||
|
||||
typedef struct {
|
||||
TreeNode *node;
|
||||
size_t index;
|
||||
} NodeWithIndex;
|
||||
|
||||
int root_index = 0;
|
||||
|
||||
PtrArray stack = wm_ptrarray_new();
|
||||
PtrArray ret = wm_ptrarray_new();
|
||||
|
||||
while (root != NULL || stack.size > 0) {
|
||||
if (root != NULL) {
|
||||
NodeWithIndex *n = malloc(sizeof(NodeWithIndex));
|
||||
n->node = root;
|
||||
n->index = root_index;
|
||||
wm_ptrarray_push(&stack, n);
|
||||
root_index = 0;
|
||||
|
||||
if (root->children.size >= 1)
|
||||
root = root->children.nodes[0];
|
||||
else root = NULL;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
NodeWithIndex *nptr;
|
||||
wm_ptrarray_pop(&stack, (void**)&nptr);
|
||||
NodeWithIndex n = *nptr;
|
||||
free(nptr);
|
||||
wm_ptrarray_push(&ret, n.node);
|
||||
|
||||
while (stack.size > 0 && n.index == ((NodeWithIndex**)stack.ptrs)
|
||||
[stack.size-1]->node->children.size - 1) {
|
||||
wm_ptrarray_pop(&stack, (void**)&nptr);
|
||||
n = *nptr;
|
||||
free(nptr);
|
||||
|
||||
wm_ptrarray_push(&ret, n.node);
|
||||
}
|
||||
|
||||
if (stack.size > 0) {
|
||||
root = ((NodeWithIndex**)stack.ptrs)[stack.size-1]->node
|
||||
->children.nodes[n.index + 1];
|
||||
root_index = n.index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
wm_ptrarray_free(&stack);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool wm_is_treenode_keyroot(TreeNode *node)
|
||||
{
|
||||
assert(node);
|
||||
if (!node->parent) return true;
|
||||
|
||||
return wm_treenode_lmd(node) != wm_treenode_lmd(node->parent);
|
||||
}
|
||||
|
||||
void wm_treenode_print(TreeNode *node)
|
||||
{
|
||||
char *str = wm_treenode_to_str(node);
|
||||
|
@ -89,7 +89,6 @@ bool wm_nodearray_remove(NodeArray *arr, size_t index);
|
||||
void __wm_nodearray_free(NodeArray *arr);
|
||||
ClientArray wm_nodearray_find_clients(TreeNode *root);
|
||||
|
||||
|
||||
PtrArray wm_ptrarray_new();
|
||||
void wm_ptrarray_push(PtrArray *arr, void* ptr);
|
||||
bool wm_ptrarray_pop(PtrArray *arr, void **ret);
|
||||
@ -103,6 +102,11 @@ TreeNode* wm_treenode_split_get_sibling(TreeNode *node);
|
||||
PtrArray wm_all_nodes_to_ptrarray(TreeNode *root);
|
||||
void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile);
|
||||
|
||||
TreeNode* wm_treenode_lmd(TreeNode *node);
|
||||
PtrArray wm_treenode_all_lmds(TreeNode *node);
|
||||
PtrArray wm_postorder_traversal(TreeNode *tree);
|
||||
bool wm_is_treenode_keyroot(TreeNode *node);
|
||||
|
||||
ClientArray wm_clientarray_new();
|
||||
void wm_clientarray_push(ClientArray *arr, Client node);
|
||||
bool wm_clientarray_pop(ClientArray *arr, Client *ret);
|
||||
|
Loading…
x
Reference in New Issue
Block a user