#pragma once #ifdef GRAPHVIZ #include #include #include #endif template class unbalanced_tree_set { struct tree_node { T data; tree_node *left = 0, *right = 0; }; tree_node *root = 0; public: void insert(const T& new_item){ tree_node *ntn = new tree_node; ntn->data = new_item; if(!root){ root = ntn; return; } tree_node *place = root; tree_node *last_place; while(place){ last_place = place; if(place->data < new_item) { place = place->right; } else if(place->data == new_item){ delete ntn; return; } else { place = place->left; } } // Node goes under last_place if(last_place->data < new_item){ last_place->right = ntn; } else { last_place->left = ntn; } } void preorder_traversal_from(auto F, tree_node *place){ F(place->data); if(place->left) preorder_traversal_from(F, place->left); if(place->right) preorder_traversal_from(F, place->right); } void preorder_traversal(auto F){ if(root) preorder_traversal_from(F, root); } void inorder_traversal_from(auto F, tree_node *place){ if(place->left) inorder_traversal_from(F, place->left); F(place->data); if(place->right) inorder_traversal_from(F, place->right); } void inorder_traversal(auto F){ if(root) inorder_traversal_from(F, root); } void postorder_traversal_from(auto F, tree_node *place){ if(place->left) postorder_traversal_from(F, place->left); if(place->right) postorder_traversal_from(F, place->right); F(place->data); } void postorder_traversal(auto F){ if(root) postorder_traversal_from(F, root); } bool contains(const T& target){ tree_node *place = root; while(place){ if(place->data == target) return true; if(place->data < target) place = place->right; else place = place->left; // this would work too: // place = (place->data < target)? place->right:place->left; } // If we're here, place was null, so we didn't find the target return false; } void delete_node(const T& target){ tree_node *place = root; tree_node **parent = &root; while(place){ if(place->data == target) break; parent = &place; if(place->data < target) { parent = &(place->right); place = place->right; } else { parent = &(place->left); place = place->left; } } if(!place) return; // We know the node is in the tree and place points to it tree_node *replacement = 0; tree_node **replacement_parent = 0; if(place->left){ replacement_parent = &place->left; replacement = place->left; while(replacement->right) replacement = replacement->right; } else if(place->right){ replacement_parent = &place->right; replacement = place->right; while(replacement->left) replacement = replacement->left; } else { *parent = replacement; } if(replacement_parent) *replacement_parent = 0; replacement->left = place->left; replacement->right = place->right; *parent = replacement; delete place; } void deallocate_tree(tree_node *place){ if(place->left) deallocate_tree(place->left); if(place->right) deallocate_tree(place->right); delete place; } ~unbalanced_tree_set(){ if(root) deallocate_tree(root); } #ifdef GRAPHVIZ void make_graph_recur(Agraph_t *g, Agnode_t *parent, tree_node *place){ Agnode_t *graphviz_place = agnode(g, (char*)std::to_string(place->data).c_str(), 1); if(parent) agedge(g, parent, graphviz_place, (char*)"", 1); if(place->left) make_graph_recur(g, graphviz_place, place->left); if(place->right) make_graph_recur(g, graphviz_place, place->right); } void make_image(const char* name){ Agraph_t *g; g = agopen((char*)"G", Agdirected, 0); make_graph_recur(g, 0, root); GVC_t* gvc = gvContext(); gvLayout(gvc, g, "dot"); gvRenderFilename(gvc, g, "png", name); gvFreeLayout(gvc, g); agclose(g); } #endif };