24template<
typename ReturnType,
typename... Types>
26 std::enable_if_t<tpf::types::is_same_v<tpf::remove_cv_ref_t<Types>...>, ReturnType>;
28template<
typename ElementType>
33 enum class visit_mode:
int{ undefined = 0, pre_order, in_order,
34 ascending_order = in_order, post_order, descending_order };
36 enum class find_mode:
int { undefined = 0, predecessor = 1, exact_match = 2, successor = 3 };
38 enum class child_status:
int { left_child = -1, no_child = 0, right_child = 1};
43 mutable int m_height{1};
54 if(m_left && child == m_left.
get())
75 auto ptr = this->
find(value);
77 return ptr && ptr->m_parent ?
78 ptr->m_parent->nearest_left_parent(ptr) :
nullptr;
84 if(m_right && child == m_right.
get())
105 auto ptr = this->
find(value);
107 return ptr && ptr->m_parent ?
108 ptr->m_parent->nearest_right_parent(ptr) :
nullptr;
111 int height(
bool bRecalculate =
false)
const
115 int left_height = 1, right_height = 1;
118 left_height += this->m_left->height(
false);
121 right_height += this->m_right->height(
false);
124 this->m_height = left_height > right_height ?
125 left_height : right_height;
128 return this->m_height;
134 auto parent_ptr = this->m_parent;
138 auto old_height = parent_ptr->m_height;
140 if(old_height != parent_ptr->height(
true))
141 parent_ptr = parent_ptr->m_parent;
149 if(this->m_left && this->m_left.get() == child)
152 else if(this->m_right && this->m_right.get() == child)
161 os <<
"node_" << this->m_value;
169 <<
" [ shape=oval, label = \"V: "
171 <<
" H:"<< this->m_height <<
" \"] ;";
188 os <<
" [style = dashed, color = red] ; " <<
nl;
190 os <<
" [style = dashed, color = blue] ; " <<
nl;
197 this->m_left->get_node_name(os) <<
" [ color = red ] ;" <<
nl;
200 this->m_left->print_node(os);
207 this->m_right->get_node_name(os) <<
" [color = blue ] ; " <<
nl;
210 this->m_right->print_node(os);
217 os <<
"digraph G { " <<
nl;
226 const ElementType&
get()
const {
return this->m_value; }
232 if(value < this->m_value)
234 if(this->m_left) this->m_left->find_raw(value);
236 else if (value > this->m_value)
238 if(this->m_right) this->m_right->find_raw(value);
262 return this->m_left->
minimum();
270 return this->m_right->
maximum();
276 m_value{value}, m_parent{parent} { }
280 template<
typename Type>
285 if(value == this->m_value)
287 else if(value < this->m_value)
291 return this->m_left->insert(std::forward<Type>(value));
296 this->m_left.reset(
new binary_node{std::forward<Type>(value),
this} );
299 this->m_left->update_height();
308 return this->m_right->insert(std::forward<Type>(value));
313 this->m_right.reset(
new binary_node{std::forward<Type>(value),
this});
316 this->m_right->update_height();
326 if(node_ptr->m_value < this->m_value)
330 return this->m_left->graft(node_ptr);
333 node_ptr->m_parent =
this;
334 this->m_left = std::move(node_ptr);
335 this->m_left->update_height();
344 return this->m_right->graft(node_ptr);
347 node_ptr->m_parent =
this;
348 this->m_right = std::move(node_ptr);
349 this->m_right->update_height();
358 template<
typename Type,
typename... Types>
364 bool result = this->
insert(std::forward<Type>(arg));
366 if constexpr(
sizeof...(args) != 0)
369 return result && this->
insert(std::forward<Types>(args)...);
384 os << this->m_value <<
", ";
387 this->m_left->visit_nodes(os, order);
390 this->m_right->visit_nodes(os, order);
397 this->m_left->visit_nodes(os, order);
400 this->m_right->visit_nodes(os, order);
402 os << this->m_value <<
", ";
410 this->m_right->visit_nodes(os, order);
412 os << this->m_value <<
", ";
415 this->m_left->visit_nodes(os, order);
424 this->m_left->visit_nodes(os, order);
426 os << this->m_value <<
", ";
429 this->m_right->visit_nodes(os, order);
445 auto ref_node = this->
find(value);
449 if(ref_node->m_right)
450 return ref_node->m_right->minimum();
451 else if(ref_node->m_parent)
452 return ref_node->m_parent->nearest_left_parent(ref_node);
462 auto ref_node = this->
find(value);
467 return ref_node->m_left->maximum();
468 else if(ref_node->m_parent)
469 return ref_node->m_parent->nearest_right_parent(ref_node);
476 return this->
find(value);
484 return (!this->m_left && !this->m_right);
489 if(this->m_left && (ptr == this->m_left.
get()))
490 return std::move(this->m_left);
491 else if(this->m_right && (ptr == this->m_right.
get()))
492 return std::move(this->m_right);
502 if(!ptr)
return false;
514 = std::move(root_ptr->m_left);
518 = std::move(root_ptr->m_right);
523 right_child->m_parent =
nullptr;
529 root_ptr = std::move(right_child);
533 root_ptr->graft(left_child);
541 left_child->m_parent =
nullptr;
545 root_ptr = std::move(left_child);
576 ptr->m_parent->m_height = 1;
591 ptr->m_parent->
height(
true);
595 std::move(orphan->m_left);
598 std::move(orphan->m_right);
601 root_ptr->graft(right_child);
604 root_ptr->graft(left_child);
613template<
typename ElementType>
616template<
typename ElementType>
620 using node_ptr_t = std::unique_ptr<binary_node_t>;
622 binary_node_t::remove_node(node_ptr, value);
655 root.visit_nodes(os, visit_mode::ascending_order);
661 root.visit_nodes(os, visit_mode::descending_order);
676 root.
insert(8, 15, 7, 9, 12, 17, 6, 16, 18, 25);
678 if(
auto ptr = root.find(6))
680 stream <<
"Value found: " << ptr->get() <<
endl;
687 if(
auto ptr = root.find(20) )
689 stream <<
"Value found: " << ptr->get() <<
endl;
708 root.
insert(8, 15, 7, 9, 12, 17, 6, 16, 18);
718 stream <<
"Usage 1: " << appname <<
" graph node_list " <<
endL;
719 stream <<
"\tExample: " << appname <<
" graph 10 8 15 7 9 12 17 6 16 18 > binary_tree.gv" <<
endL;
720 stream <<
"\tdot -Tpng binary_tree.gv -o binary_tree.png" <<
endL;
722 stream <<
"Usage 2: " << appname <<
" list node_list " <<
endL;
723 stream <<
"\tExample: " << appname <<
" list 10 8 15 7 9 12 17 6 16 18" <<
endL;
725 stream <<
"Usage 3: " << appname <<
" {ascending|desecnding} {successor_of|predecessor_of|exact_match_of} value node_list " <<
endL;
726 stream <<
"\tExample: " << appname <<
" ascending successor_of 19 10 8 15 7 9 12 17 6 16 18" <<
endL;
727 stream <<
"\t\t" <<
" Finds the successor of 19 in ascending order from the list 10 8 15 7 9 12 17 6 16 18" <<
endL;
729 stream <<
"Usage 4: " << appname <<
" remove value node_list " <<
endL;
730 stream <<
"\tExample: " << appname <<
" remove 19 10 8 15 7 9 12 17 6 16 18" <<
endL;
731 stream <<
"\t\t" <<
" Find and remove node with value 19 from the list 10 8 15 7 9 12 17 6 16 18" <<
endL;
733 stream <<
"Usage 5: " << appname <<
" find value node_list " <<
endL;
734 stream <<
"\tExample: " << appname <<
" find 19 10 8 15 7 9 12 17 6 16 18" <<
endL;
735 stream <<
"\t\t" <<
" Find 19 from the list 10 8 15 7 9 12 17 6 16 18" <<
endL;
737 stream <<
"Usage 6: " << appname <<
" min_max node_list " <<
endL;
738 stream <<
"\tExample: " << appname <<
" min_max 10 8 15 7 9 12 17 6 16 18" <<
endL;
739 stream <<
"\t\t" <<
" Find minimum and maximum from the list 10 8 15 7 9 12 17 6 16 18" <<
endL;
741 stream <<
"Usage 7: " << appname <<
" nearest_parents value node_list " <<
endL;
742 stream <<
"\tExample: " << appname <<
" nearest_parents 9 10 8 15 7 9 12 17 6 16 18" <<
endL;
743 stream <<
"\t\t" <<
" Find the nearest left/right parents of node 9 from the list 10 8 15 7 9 12 17 6 16 18" <<
endL;
746int main(
int argc,
const char* argv[])
756 print_usage(appname,
"Program commandline syntax");
763 if(command ==
"graph")
767 for(
int i = 3; i < argc; ++i)
769 root.
insert( std::atoi(argv[i]) );
774 else if(command ==
"list")
779 for(
int i = 3; i < argc; ++i)
781 root.
insert( std::atoi(argv[i]) );
784 stream <<
"Ascending order: ";
785 root.visit_nodes(
stream, visit_mode::ascending_order);
788 stream <<
"Descending order: ";
789 root.visit_nodes(
stream, visit_mode::descending_order);
792 else if(command ==
"ascending"
793 || command ==
"descending")
799 find_mode fmode {find_mode::undefined};
801 if(command ==
"ascending")
802 vmode = visit_mode::ascending_order;
804 if(command ==
"descending")
805 vmode = visit_mode::descending_order;
807 if(vmode==visit_mode::undefined)
821 if(operation ==
"successor_of")
822 fmode = find_mode::successor;
824 if(operation ==
"predecessor_of")
825 fmode = find_mode::predecessor;
827 if(operation ==
"exact_match_of")
828 fmode = find_mode::exact_match;
830 if(fmode == find_mode::undefined)
836 int value = std::atoi(argv[3]);
841 for(
int i = 5; i < argc; ++i)
843 root.
insert( std::atoi(argv[i]) );
846 stream <<
"Ascending order: ";
847 root.visit_nodes(
stream, visit_mode::ascending_order);
850 stream <<
"Descending order: ";
851 root.visit_nodes(
stream, visit_mode::descending_order);
854 auto ptr = root.find(value, fmode, vmode);
858 if(fmode == find_mode::successor)
859 stream <<
"The successor of " << value;
860 else if (fmode == find_mode::predecessor)
861 stream <<
"The predecessor of " << value;
862 else if (fmode == find_mode::exact_match)
863 stream <<
"The exact match of " << value;
865 if(vmode == visit_mode::ascending_order)
866 stream <<
" in ascending order is ";
868 if(vmode == visit_mode::descending_order)
869 stream <<
" in descending order is ";
875 if(fmode == find_mode::successor)
876 stream <<
"The successor of " << value;
877 else if (fmode == find_mode::predecessor)
878 stream <<
"The predecessor of " << value;
879 else if (fmode == find_mode::exact_match)
880 stream <<
"The exact match of " << value;
882 if(vmode == visit_mode::ascending_order)
883 stream <<
" in ascending order is NOT found";
885 if(vmode == visit_mode::descending_order)
886 stream <<
" in descending order NOT found ";
891 else if(command ==
"remove")
894 using node_ptr_t = std::unique_ptr<binary_node_t>;
903 int value = std::atoi(argv[2]);
905 node_ptr_t root = std::make_unique<binary_node_t>(std::atoi(argv[3]));
907 for(
int i = 4; i < argc; ++i)
909 root->insert( std::atoi(argv[i]) );
914 else if(command ==
"find")
917 using node_ptr_t = std::unique_ptr<binary_node_t>;
926 int value = std::atoi(argv[2]);
928 node_ptr_t root = std::make_unique<binary_node_t>(std::atoi(argv[3]));
930 for(
int i = 4; i < argc; ++i)
932 root->insert( std::atoi(argv[i]) );
935 binary_node_t* ptr = root->find(value);
939 stream <<
"We found value: " << value <<
endl;
943 stream <<
"We failed to find the value: " << value <<
endl;
947 else if(command ==
"nearest_parents")
950 using node_ptr_t = std::unique_ptr<binary_node_t>;
959 int value = std::atoi(argv[2]);
961 node_ptr_t root = std::make_unique<binary_node_t>(std::atoi(argv[3]));
963 for(
int i = 4; i < argc; ++i)
965 root->insert( std::atoi(argv[i]) );
968 auto left_parent_ptr = root->nearest_left_parent(value);
971 stream <<
"The nearest left parent of the node "
972 << value <<
" is " << left_parent_ptr->get() <<
endl;
976 stream <<
"The nearest left parent of the node "
977 << value <<
" is NOT foound." <<
endl;
980 auto right_parent_ptr = root->nearest_right_parent(value);
983 stream <<
"The nearest right parent of the node "
984 << value <<
" is " << right_parent_ptr->get() <<
endl;
988 stream <<
"The nearest right parent of the node "
989 << value <<
" is NOT foound." <<
endl;
993 else if(command ==
"min_max")
996 using node_ptr_t = std::unique_ptr<binary_node_t>;
1005 node_ptr_t root = std::make_unique<binary_node_t>(std::atoi(argv[2]));
1007 for(
int i = 3; i < argc; ++i)
1009 root->insert( std::atoi(argv[i]) );
1012 binary_node_t* ptr_min = root->minimum();
1016 stream <<
"We found minim value: " << ptr_min->get() <<
endl;
1020 stream <<
"We failed to find minimum value " <<
endl;
1024 binary_node_t* ptr_max = root->maximum();
1028 stream <<
"We found maximum value: " << ptr_max->get() <<
endl;
1032 stream <<
"We failed to find maximum value " <<
endl;
std::enable_if_t< tpf::types::is_same_v< tpf::remove_cv_ref_t< Types >... >, ReturnType > enable_if_all_types_are_the_same_t
typename binary_node< ElementType >::node_ptr_t node_ptr_t
void test_remove_node(node_ptr_t< ElementType > &node_ptr, ElementType value)
void print_usage(string_t appname, const char *msg)
void test_ascending_descending_order()
void test_find_binary_tree()
int main(int argc, const char *argv[])
void test_build_digraph()
typename graph_t::visit_mode visit_mode
void nearest_left_parent_raw(binary_node *child)
static bool remove_node(node_ptr_t &root_ptr, ElementType value)
binary_node * find(ElementType value)
enable_if_all_types_are_the_same_t< bool, ElementType, Type, Types... > insert(Type &&arg, Types &&... args)
child_status get_child_status(binary_node *child)
void find_raw(ElementType value)
tpf::sstream & get_node_name(tpf::sstream &os)
bool graft(node_ptr_t &node_ptr)
binary_node * nearest_right_parent(ElementType value)
binary_node * nearest_left_parent(ElementType value)
void nearest_right_parent_raw(binary_node *child)
const ElementType & get() const
node_ptr_t release_child(binary_node *ptr)
void print_node(tpf::sstream &os)
std::unique_ptr< binary_node > node_ptr_t
tpf::sstream & get_node_definition(tpf::sstream &os)
bool insert(ElementType value)
binary_node * nearest_right_parent(binary_node *child)
enable_if_all_types_are_the_same_t< bool, ElementType, Type > insert(Type &&value)
binary_node * find(ElementType value, find_mode fmode, visit_mode vmode=visit_mode::ascending_order)
binary_node(ElementType value=ElementType{}, binary_node *parent=nullptr)
binary_node * nearest_left_parent(binary_node *child)
int height(bool bRecalculate=false) const
void visit_nodes(tpf::sstream &os, visit_mode order=visit_mode::in_order)
Stream output operators << are implemented.