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);
|
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)
|
void wm_treenode_print(TreeNode *node)
|
||||||
{
|
{
|
||||||
char *str = wm_treenode_to_str(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);
|
void __wm_nodearray_free(NodeArray *arr);
|
||||||
ClientArray wm_nodearray_find_clients(TreeNode *root);
|
ClientArray wm_nodearray_find_clients(TreeNode *root);
|
||||||
|
|
||||||
|
|
||||||
PtrArray wm_ptrarray_new();
|
PtrArray wm_ptrarray_new();
|
||||||
void wm_ptrarray_push(PtrArray *arr, void* ptr);
|
void wm_ptrarray_push(PtrArray *arr, void* ptr);
|
||||||
bool wm_ptrarray_pop(PtrArray *arr, void **ret);
|
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);
|
PtrArray wm_all_nodes_to_ptrarray(TreeNode *root);
|
||||||
void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile);
|
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();
|
ClientArray wm_clientarray_new();
|
||||||
void wm_clientarray_push(ClientArray *arr, Client node);
|
void wm_clientarray_push(ClientArray *arr, Client node);
|
||||||
bool wm_clientarray_pop(ClientArray *arr, Client *ret);
|
bool wm_clientarray_pop(ClientArray *arr, Client *ret);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user