implement tree edit distance utility functions

This commit is contained in:
Akos Horvath 2023-12-28 15:59:07 +01:00
parent 557a43e265
commit a0f2f48ef2
2 changed files with 97 additions and 1 deletions

View File

@ -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);

View File

@ -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);