#ifndef _UTIL_BINARY_SEARCH_TREE_H #define _UTIL_BINARY_SEARCH_TREE_H #include #include "binary_tree.h" template struct BinarySearchTreePair { K key; V value; }; template using BinarySearchTree = BinaryTree>; template void binary_search_tree_clear(BinarySearchTree*& root, std::function free_key = std::function(), std::function free_value = std::function()) { if (free_key || free_value) { binary_tree_clear(root, [&free_key, &free_value](BinarySearchTreePair e) { if (free_key) free_key(e.key); if (free_value) free_value(e.value); }); } else { binary_tree_clear(root); } } template inline void binary_search_tree_clear(BinarySearchTree*& root, F free_key, G free_value = nullptr) { binary_search_tree_clear(root, std::function(free_key), std::function(free_value)); } template bool binary_search_tree_delete(BinarySearchTree*& root, K key, V* deleted_value, std::function comp, std::function free_key = std::function(), std::function free_value = std::function()) { if (!root) return false; BinarySearchTree* cur = root, *prev = nullptr; while (cur) { int re = comp(key, cur->data.key); if (re == 0) { break; } prev = cur; cur = re < 0 ? cur->left : cur->right; } if (!cur) return false; if (binary_tree_is_leaf(cur)) { if (prev) prev->left == cur ? prev->left = nullptr : prev->right = nullptr; else root = nullptr; } else if (!cur->right) { if (prev) prev->left == cur ? prev->left = cur->left : prev->right = cur->left; else root = cur->left; } else if (!cur->left) { if (prev) prev->left == cur ? prev->left = cur->right : prev->right = cur->right; else root = cur->right; } else { prev = cur; BinarySearchTree* tmp = cur->left; while (tmp->right) { prev = tmp; tmp = tmp->right; } K tk = tmp->data.key; V tv = tmp->data.value; tmp->data.key = cur->data.key; tmp->data.value = cur->data.value; cur->data.key = tk; cur->data.value = tv; cur = tmp; prev->left == cur ? prev->left = nullptr : prev->right = nullptr; } if (free_key) free_key(cur->data.key); if (deleted_value) *deleted_value = cur->data.value; if (!deleted_value && free_value) free_value(cur->data.value); free(cur); return true; } template inline bool binary_search_tree_delete(BinarySearchTree*& root, K key, V* deleted_value, F comp, G free_key, H free_value) { return binary_search_tree_delete(root, key, deleted_value, std::function(comp), std::function(free_key), std::function(free_value)); } template bool binary_search_tree_delete(BinarySearchTree*& root, K key, V* deleted_value = nullptr) { return binary_search_tree_delete(root, key, deleted_value, [](K k1, K k2) { return k1 == k2 ? 0 : k1 < k2 ? -1 : 1; }, nullptr, nullptr); } template bool binary_search_tree_get(BinarySearchTree* root, K key, V& value, std::function comp) { if (!root) return false; BinarySearchTree* cur = root; while (cur) { int re = comp(key, cur->data.key); if (re == 0) { value = cur->data.value; return true; } cur = re < 0 ? cur->left : cur->right; } return false; } template inline bool binary_search_tree_get(BinarySearchTree* root, K key, V& value, F comp) { return binary_search_tree_get(root, key, value, std::function(comp)); } template bool binary_search_tree_get(BinarySearchTree* root, K key, V& value) { return binary_search_tree_get(root, key, value, [](K k1, K k2) { return k1 == k2 ? 0 : k1 < k2 ? -1 : 1; }); } template BinarySearchTree* binary_search_tree_get_node(BinarySearchTree* root, K key, std::function comp) { if (!root) return nullptr; BinarySearchTree* cur = root; while (cur) { int re = comp(key, cur->data.key); if (re == 0) { return cur; } cur = re < 0 ? cur->left : cur->right; } return nullptr; } template inline BinarySearchTree* binary_search_tree_get_node(BinarySearchTree* root, K key, F comp) { return binary_search_tree_get_node(root, key, std::function(comp)); } template BinarySearchTree* binary_search_tree_get_node(BinarySearchTree* root, K key) { return binary_search_tree_get_node(root, key, [](K k1, K k2) { return k1 == k2 ? 0 : k1 < k2 ? -1 : 1; }); } template void binary_search_tree_iter(BinarySearchTree* root, std::function callback, Args... args) { binary_tree_lnr(root, [&callback](BinarySearchTree* e, Args... args) { callback(e->data.key, e->data.value, args...); }, args...); } template inline void binary_search_tree_iter(BinarySearchTree* root, F callback, Args... args) { binary_search_tree_iter(root, std::function(callback), args...); } template BinarySearchTree* binary_search_tree_insert(BinarySearchTree*& root, K key, V value, std::function comp, std::function free_key = std::function(), std::function free_value = std::function(), bool noupdate = false) { if (!root) { root = binary_tree_new>({ key, value }); if (!root) { if (free_key) free_key(key); if (free_value) free_value(value); } return root; } BinarySearchTree* cur = root; int re = comp(key, cur->data.key); while (!binary_tree_is_leaf(cur)) { if (re == 0) { break; } if (re < 0 && !cur->left) break; if (re > 0 && !cur->right) break; cur = re < 0 ? cur->left : cur->right; re = comp(key, cur->data.key); } if (re == 0) { if (free_value && !noupdate) free_value(cur->data.value); if (free_key) free_key(key); if (!noupdate) cur->data.value = value; return cur; } BinarySearchTree* node = binary_tree_new>({key, value}); if (!node) { if (free_key) free_key(key); if (free_value) free_value(value); return nullptr; } if (re == -1) { cur->left = node; } else { cur->right = node; } return node; } template inline BinarySearchTree* binary_search_tree_insert(BinarySearchTree*& root, K key, V value, F comp) { return binary_search_tree_insert(root, key, value, std::function(comp)); } template BinarySearchTree* binary_search_tree_insert(BinarySearchTree*& root, K key, V value) { return binary_search_tree_insert(root, key, value, [](K k1, K k2) { return k1 == k2 ? 0 : k1 < k2 ? -1 : 1; }); } template > class BinarySearchMap { private: BinarySearchTree* tree = nullptr; std::function comp_func; std::function free_key_func; std::function free_value_func; public: BinarySearchMap(std::function free_key = std::function(), std::function free_value = std::function(), Compare cmp = Compare()) { comp_func = std::function([&cmp] (K k1, K k2) { return cmp(k1, k2) ? -1 : cmp(k2, k1) ? 1 : 0; }); free_key_func = free_key; free_value_func = free_value; } template BinarySearchMap(F free_key, G free_value = std::function(), Compare cmp = Compare()) : BinarySearchMap(std::function(free_key), std::function(free_value), cmp) {} BinarySearchMap(const BinarySearchMap& other) { tree = binary_tree_clone(other.tree, [&other](BinarySearchTreePair e) { if (other.free_key_func) other.free_key_func(e.key); if (other.free_value_func) other.free_value_func(e.value); }); if (!tree) { throw std::runtime_error("Failed to clone map."); } comp_func = other.comp_func; free_key_func = other.free_key_func; free_value_func = other.free_value_func; } ~BinarySearchMap() { clear(); } void inline clear() { binary_search_tree_clear(tree, free_key_func, free_value_func); } bool inline del(K key, V* deleted_value = nullptr) { return binary_search_tree_delete(tree, key, deleted_value, comp_func, free_key_func, free_value_func); } bool inline get(K key, V& value) const { return binary_search_tree_get(tree, key, value, comp_func); } bool inline get(K key, V& value) { return binary_search_tree_get(tree, key, value, comp_func); } bool inline insert(K key, V value) { return binary_search_tree_insert(tree, key, value, comp_func, free_key_func, free_value_func) != nullptr; } template void inline iter(std::function callback, Args... args) { return binary_search_tree_iter(tree, callback, args...); } template void inline iter(F callback, Args... args) { return binary_search_tree_iter(tree, std::function(callback), args...); } const V& operator[](K key) const { BinarySearchTree* node = binary_search_tree_get_node(tree, key, comp_func); if (!node) { throw std::runtime_error("No such node."); } return node->data.value; } V& operator[](K key) { V tmp = V(); BinarySearchTree* node = binary_search_tree_insert(tree, key, tmp, comp_func, free_key_func, free_value_func, true); if (!node) { throw std::runtime_error("Failed to insert new node."); } return node->data.value; } }; #endif