#ifndef _UTIL_BINARY_TREE_H #define _UTIL_BINARY_TREE_H #include #include #include #include #include "linked_queue.h" template struct BinaryTree { T data; struct BinaryTree* left; struct BinaryTree* right; }; template void binary_tree_clear(struct BinaryTree*& top, std::function free_func = std::function()) { if (!top) return; binary_tree_dfs(top, [&free_func](struct BinaryTree* node) { if (free_func) { free_func(node->data); } node->left = nullptr; node->right = nullptr; free(node); }); top = nullptr; } template inline void binary_tree_clear(struct BinaryTree*& top, F free_func) { binary_tree_clear(top, std::function(free_func)); } template struct BinaryTree* binary_tree_clone(struct BinaryTree* tree, std::function free_func = std::function()) { if (!tree) return nullptr; T newdata(tree->data); struct BinaryTree* now = binary_tree_new(newdata); if (now) { if (tree->left) { now->left = binary_tree_clone(tree->left, free_func); if (!now->left) goto end; } if (tree->right) { now->right = binary_tree_clone(tree->right, free_func); if (!now->right) goto end; } } return now; end: binary_tree_clear(now, free_func); return now; } template inline struct BinaryTree* binary_tree_clone(struct BinaryTree* tree, F free_func) { return binary_tree_clone(tree, std::function(free_func)); } template void binary_tree_dfs(struct BinaryTree* top, std::function*, Args...)> callback, Args... args) { if (!top) return; if (top->left) binary_tree_dfs(top->left, callback, args...); if (top->right) binary_tree_dfs(top->right, callback, args...); callback(top, args...); } template inline void binary_tree_dfs(struct BinaryTree* top, F callback, Args... args) { binary_tree_dfs(top, std::function*, Args...)>(callback), args...); } #define binary_tree_lrn binary_tree_dfs template void binary_tree_lnr(struct BinaryTree* top, std::function*, Args...)> callback, Args... args) { if (!top) return; if (top->left) binary_tree_lnr(top->left, callback, args...); callback(top, args...); if (top->right) binary_tree_lnr(top->right, callback, args...); } template inline void binary_tree_lnr(struct BinaryTree* top, F callback, Args... args) { binary_tree_lnr(top, std::function*, Args...)>(callback), args...); } template void binary_tree_nlr(struct BinaryTree* top, std::function*, Args...)> callback, Args... args) { if (!top) return; callback(top, args...); if (top->left) binary_tree_nlr(top->left, callback, args...); if (top->right) binary_tree_nlr(top->right, callback, args...); } template inline void binary_tree_nlr(struct BinaryTree* top, F callback, Args... args) { binary_tree_nlr(top, std::function*, Args...)>(callback), args...); } template void binary_tree_bfs(struct BinaryTree* top, std::function*, Args...)> callback, Args... args) { if (!top) return; struct LinkedQueue*> queue; linked_queue_init(queue); linked_queue_push(queue, top); struct BinaryTree* tmp; while (linked_queue_pop(queue, tmp)) { if (tmp->left) linked_queue_push(queue, tmp->left); if (tmp->right) linked_queue_push(queue, tmp->right); callback(tmp, args...); } } template inline void binary_tree_bfs(struct BinaryTree* top, F callback, Args... args) { binary_tree_bfs(top, std::function*, Args...)>(callback), args...); } template struct BinaryTree* binary_tree_new(T data) { struct BinaryTree* node = (struct BinaryTree*)malloc(sizeof(struct BinaryTree)); if (!node) return nullptr; node->data = data; node->left = nullptr; node->right = nullptr; return node; } template inline bool binary_tree_is_leaf(struct BinaryTree* node) { return node->left == nullptr && node->right == nullptr; } template inline bool binary_tree_node_is_full(struct BinaryTree* node) { return node->left != nullptr && node->right != nullptr; } #endif