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};
52 int height(
bool bRecalculate =
false)
const
56 int left_height = 1, right_height = 1;
59 left_height += this->m_left->height(
false);
62 right_height += this->m_right->height(
false);
65 this->m_height = left_height > right_height ?
66 left_height : right_height;
69 return this->m_height;
75 auto parent_ptr = this->m_parent;
79 auto old_height = parent_ptr->m_height;
81 if(old_height != parent_ptr->height(
true))
82 parent_ptr = parent_ptr->m_parent;
90 if(this->m_left && this->m_left.get() == child)
93 else if(this->m_right && this->m_right.get() == child)
102 os <<
"node_" << this->m_value;
110 <<
" [ shape=oval, label = \"V:"
112 <<
" H:"<< this->m_height <<
"\"] ;";
129 os <<
" [style = dashed, color = red] ; " <<
nl;
131 os <<
" [style = dashed, color = blue] ; " <<
nl;
138 this->m_left->get_node_name(os) <<
" [ color = red ] ;" <<
nl;
141 this->m_left->print_node(os);
148 this->m_right->get_node_name(os) <<
" [color = blue ] ; " <<
nl;
151 this->m_right->print_node(os);
158 os <<
"digraph G { " <<
nl;
167 const ElementType&
get()
const {
return this->m_value; }
174 if(value == this->m_value)
180 if(this->m_left && (ptr = this->m_left->
find(value)))
183 if(this->m_right && (ptr = this->m_right->
find(value)))
190 m_value{value}, m_parent{parent} { }
194 template<
typename Type>
199 if(value == this->m_value)
201 else if(value < this->m_value)
205 return this->m_left->insert(std::forward<Type>(value));
210 this->m_left.reset(
new binary_node{std::forward<Type>(value),
this} );
213 this->m_left->update_height();
222 return this->m_right->insert(std::forward<Type>(value));
227 this->m_right.reset(
new binary_node{std::forward<Type>(value),
this});
230 this->m_right->update_height();
239 if( node_ptr->m_value == this->m_value)
241 else if(node_ptr->m_value < this->m_value)
245 return this->m_left->graft( std::move(node_ptr) );
248 node_ptr->m_parent =
this;
249 this->m_left = std::move(node_ptr);
250 this->m_left->update_height();
259 return this->m_right->graft(std::move(node_ptr));
262 node_ptr->m_parent =
this;
263 this->m_right = std::move(node_ptr);
264 this->m_right->update_height();
273 template<
typename Type,
typename... Types>
279 bool result = this->
insert(std::forward<Type>(arg));
281 if constexpr(
sizeof...(args) != 0)
284 return result && this->
insert(std::forward<Types>(args)...);
299 os << this->m_value <<
", ";
302 this->m_left->visit_nodes(os, order);
305 this->m_right->visit_nodes(os, order);
312 this->m_left->visit_nodes(os, order);
315 this->m_right->visit_nodes(os, order);
317 os << this->m_value <<
", ";
325 this->m_right->visit_nodes(os, order);
327 os << this->m_value <<
", ";
330 this->m_left->visit_nodes(os, order);
339 this->m_left->visit_nodes(os, order);
341 os << this->m_value <<
", ";
344 this->m_right->visit_nodes(os, order);
360 if(this->m_left && (ptr = this->m_left->
find(value, fmode, vmode)))
363 if( value < this->m_value)
366 if(this->m_right && (ptr = this->m_right->
find(value, fmode, vmode)))
375 if(this->m_right && (ptr = this->m_right->
find(value, fmode, vmode)))
378 if(value > this->m_value)
381 if(this->m_left && (ptr = this->m_left->
find(value, fmode, vmode)))
387 return this->
find(value);
397 if(!ptr)
return false;
409 = std::move(root_ptr->m_left);
413 = std::move(root_ptr->m_right);
418 right_child->m_parent =
nullptr;
424 root_ptr = std::move(right_child);
428 root_ptr->graft(std::move(left_child));
436 left_child->m_parent =
nullptr;
440 root_ptr = std::move(left_child);
462template<
typename ElementType>
465template<
typename ElementType>
469 using node_ptr_t = std::unique_ptr<binary_node_t>;
471 binary_node_t::remove_node(node_ptr, value);
504 root.visit_nodes(os, visit_mode::ascending_order);
510 root.visit_nodes(os, visit_mode::descending_order);
525 root.
insert(8, 15, 7, 9, 12, 17, 6, 16, 18, 25);
527 if(
auto ptr = root.find(6))
529 stream <<
"Value found: " << ptr->get() <<
endl;
536 if(
auto ptr = root.find(20) )
538 stream <<
"Value found: " << ptr->get() <<
endl;
557 root.
insert(8, 15, 7, 9, 12, 17, 6, 16, 18);
567 stream <<
"Usage 1: " << appname <<
" graph node_list " <<
endL;
568 stream <<
"\tExample: " << appname <<
" graph 10 8 15 7 9 12 17 6 16 18 > binary_tree.gv" <<
endL;
569 stream <<
"\tdot -Tpng binary_tree.gv -o binary_tree.png" <<
endL;
571 stream <<
"Usage 2: " << appname <<
" list node_list " <<
endL;
572 stream <<
"\tExample: " << appname <<
" list 10 8 15 7 9 12 17 6 16 18" <<
endL;
574 stream <<
"Usage 3: " << appname <<
" {ascending|desecnding} {successor_of|predecessor_of|exact_match_of} value node_list " <<
endL;
575 stream <<
"\tExample: " << appname <<
" ascending successor_of 19 10 8 15 7 9 12 17 6 16 18" <<
endL;
576 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;
578 stream <<
"Usage 4: " << appname <<
" remove value node_list " <<
endL;
579 stream <<
"\tExample: " << appname <<
" remove 19 10 8 15 7 9 12 17 6 16 18" <<
endL;
580 stream <<
"\t\t" <<
" Find and remove node with value 19 from the list 10 8 15 7 9 12 17 6 16 18" <<
endL;
583int main(
int argc,
const char* argv[])
593 print_usage(appname,
"Program commandline syntax");
600 if(command ==
"graph")
604 for(
int i = 3; i < argc; ++i)
606 root.
insert( std::atoi(argv[i]) );
611 else if(command ==
"list")
616 for(
int i = 3; i < argc; ++i)
618 root.
insert( std::atoi(argv[i]) );
621 stream <<
"Ascending order: ";
622 root.visit_nodes(
stream, visit_mode::ascending_order);
625 stream <<
"Descending order: ";
626 root.visit_nodes(
stream, visit_mode::descending_order);
629 else if(command ==
"ascending"
630 || command ==
"descending")
636 find_mode fmode {find_mode::undefined};
638 if(command ==
"ascending")
639 vmode = visit_mode::ascending_order;
641 if(command ==
"descending")
642 vmode = visit_mode::descending_order;
644 if(vmode==visit_mode::undefined)
658 if(operation ==
"successor_of")
659 fmode = find_mode::successor;
661 if(operation ==
"predecessor_of")
662 fmode = find_mode::predecessor;
664 if(operation ==
"exact_match_of")
665 fmode = find_mode::exact_match;
667 if(fmode == find_mode::undefined)
673 int value = std::atoi(argv[3]);
678 for(
int i = 5; i < argc; ++i)
680 root.
insert( std::atoi(argv[i]) );
683 stream <<
"Ascending order: ";
684 root.visit_nodes(
stream, visit_mode::ascending_order);
687 stream <<
"Descending order: ";
688 root.visit_nodes(
stream, visit_mode::descending_order);
691 auto ptr = root.find(value, fmode, vmode);
695 if(fmode == find_mode::successor)
696 stream <<
"The successor of " << value;
697 else if (fmode == find_mode::predecessor)
698 stream <<
"The predecessor of " << value;
699 else if (fmode == find_mode::exact_match)
700 stream <<
"The exact match of " << value;
702 if(vmode == visit_mode::ascending_order)
703 stream <<
" in ascending order is ";
705 if(vmode == visit_mode::descending_order)
706 stream <<
" in descending order is ";
712 if(fmode == find_mode::successor)
713 stream <<
"The successor of " << value;
714 else if (fmode == find_mode::predecessor)
715 stream <<
"The predecessor of " << value;
716 else if (fmode == find_mode::exact_match)
717 stream <<
"The exact match of " << value;
719 if(vmode == visit_mode::ascending_order)
720 stream <<
" in ascending order is NOT found";
722 if(vmode == visit_mode::descending_order)
723 stream <<
" in descending order NOT found ";
728 else if(command ==
"remove")
731 using node_ptr_t = std::unique_ptr<binary_node_t>;
740 int value = std::atoi(argv[2]);
742 node_ptr_t root = std::make_unique<binary_node_t>(std::atoi(argv[3]));
744 for(
int i = 4; i < argc; ++i)
746 root->insert( std::atoi(argv[i]) );
std::enable_if_t< tpf::types::is_same_v< tpf::remove_cv_ref_t< Types >... >, ReturnType > enable_if_all_types_are_the_same_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[])
typename binary_node< ElementType >::node_ptr_t node_ptr_t
void test_build_digraph()
typename graph_t::visit_mode visit_mode
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)
tpf::sstream & get_node_name(tpf::sstream &os)
bool graft(node_ptr_t node_ptr)
const ElementType & get() const
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)
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)
int height(bool bRecalculate=false) const
void visit_nodes(tpf::sstream &os, visit_mode order=visit_mode::in_order)
Stream output operators << are implemented.