C++ Library Extensions 2022.12.09
To help learn modern C++ programming
058-binary_tree10.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
2
3/*
4 binary_tree 50 17 72 12 23 54 76 9 14 19 67 > old.txt
5
6 binary_tree 50 17 72 12 23 54 76 9 14 19 67 25 > new.txt
7
8 binary_tree 50 17 72 12 23 54 76 9 14 19 67 25 18> newnew.txt
9
10 https://edotor.net/
11
12 */
13
15
16auto endl = tpf::endl; // single carriage return and flush to console output
17auto endL = tpf::endL; // double carriage returns and flush to console output
18
19auto nl = tpf::nl; // single carriage return without flush
20auto nL = tpf::nL; // double carriage returns without flush
21
22using string_t = std::string;
23
24template<typename ReturnType, typename... Types>
26 std::enable_if_t<tpf::types::is_same_v<tpf::remove_cv_ref_t<Types>...>, ReturnType>;
27
28template<typename ElementType>
29class binary_node
30{
31 public:
32 using node_ptr_t = std::unique_ptr<binary_node>;
33 enum class visit_mode: int{ undefined = 0, pre_order, in_order,
34 ascending_order = in_order, post_order, descending_order };
35
36 enum class find_mode: int { undefined = 0, predecessor = 1, exact_match = 2, successor = 3 };
37
38 enum class child_status: int { left_child = -1, no_child = 0, right_child = 1};
39 private:
40
41 ElementType m_value; // node's value
42
43 mutable int m_height{1}; // the height of a node
44
45 binary_node* m_parent; // pointer to point to the parent node
46
47 node_ptr_t m_left; // left child node
48 node_ptr_t m_right; // right child node
49
50 public:
51
53 {
54 if(m_left && child == m_left.get())
55 throw this;
56 else if(m_parent)
57 m_parent->nearest_left_parent_raw(this);
58 }
59
61 {
62 try
63 {
64 this->nearest_left_parent_raw(child);
65 return nullptr; // we failed to find the nearest left parent
66 }
67 catch(binary_node* ptr)
68 {
69 return ptr; // we found the nearest left parent
70 }
71 }
72
73 binary_node* nearest_left_parent(ElementType value)
74 {
75 auto ptr = this->find(value);
76
77 return ptr && ptr->m_parent ?
78 ptr->m_parent->nearest_left_parent(ptr) : nullptr;
79 }
80
83 {
84 if(m_right && child == m_right.get())
85 throw this;
86 else if(m_parent)
87 m_parent->nearest_right_parent_raw(this);
88 }
89
91 {
92 try
93 {
94 this->nearest_right_parent_raw(child);
95 return nullptr; // we failed to find the nearest left parent
96 }
97 catch(binary_node* ptr)
98 {
99 return ptr; // we found the nearest left parent
100 }
101 }
102
104 {
105 auto ptr = this->find(value);
106
107 return ptr && ptr->m_parent ?
108 ptr->m_parent->nearest_right_parent(ptr) : nullptr;
109 }
110
111 int height(bool bRecalculate = false) const
112 {
113 if(bRecalculate) // if bRecalculate is true,
114 { // we will recalculate the m_height member
115 int left_height = 1, right_height = 1;
116
117 if(this->m_left)
118 left_height += this->m_left->height(false); // false means we use cached value of m_height
119
120 if(this->m_right)
121 right_height += this->m_right->height(false); // false means we use cached value of m_height
122
123 // m_height is the greater of the two, left_height and right_height
124 this->m_height = left_height > right_height ?
125 left_height : right_height;
126 }
127
128 return this->m_height;
129 }
130
132 {
133 // the parent ptr of the current node
134 auto parent_ptr = this->m_parent;
135
136 while(parent_ptr)
137 {
138 auto old_height = parent_ptr->m_height;
139
140 if(old_height != parent_ptr->height(true))
141 parent_ptr = parent_ptr->m_parent;
142 else
143 break;
144 }
145 }
146
148 {
149 if(this->m_left && this->m_left.get() == child)
150
152 else if(this->m_right && this->m_right.get() == child)
153
155 else
157 }
158
160 {
161 os << "node_" << this->m_value;
162 return os;
163 }
164
166 {
167 // node_1 [ shape=box, label = " Root "] ;
168 get_node_name(os)
169 << " [ shape=oval, label = \"V: "
170 << this->m_value
171 << " H:"<< this->m_height << " \"] ;";
172
173 return os;
174 }
175
177 {
178 get_node_definition(os) << nl;
179
180 if(this->m_parent)
181 {
182 get_node_name(os) << " -> ";
183 this->m_parent->get_node_name(os);
184
185 auto status = this->m_parent->get_child_status(this);
186
187 if(status == child_status::left_child)
188 os << " [style = dashed, color = red] ; " << nl;
189 else if (status == child_status::right_child)
190 os << " [style = dashed, color = blue] ; " << nl;
191 }
192
193 // root -> left
194 if(this->m_left)
195 {
196 get_node_name(os) << " -> ";
197 this->m_left->get_node_name(os) << " [ color = red ] ;" << nl;
198
199 // recursion for left children
200 this->m_left->print_node(os);
201 }
202
203 // root -> right
204 if(this->m_right)
205 {
206 get_node_name(os) << " -> ";
207 this->m_right->get_node_name(os) << " [color = blue ] ; " << nl;
208
209 // recursion for right children
210 this->m_right->print_node(os);
211 }
212 }
214 {
215 tpf::sstream os;
216
217 os << "digraph G { " << nl;
218
219 print_node(os);
220
221 os <<"}";
222
223 return os.str();
224 }
225
226 const ElementType& get() const { return this->m_value; }
227
228 // if value is not found,
229 // this function returns nullptr
230 void find_raw(ElementType value)
231 {
232 if(value < this->m_value)
233 {
234 if(this->m_left) this->m_left->find_raw(value);
235 }
236 else if (value > this->m_value)
237 {
238 if(this->m_right) this->m_right->find_raw(value);
239 }
240 else
241 {
242 throw this;
243 }
244 }
245
246 binary_node* find(ElementType value)
247 {
248 try
249 {
250 this->find_raw(value);
251 return nullptr;
252 }
253 catch(binary_node* ptr)
254 {
255 return ptr;
256 }
257 }
258
260 {
261 if(this->m_left)
262 return this->m_left->minimum();
263 else
264 return this;
265 }
266
268 {
269 if(this->m_right)
270 return this->m_right->maximum();
271 else
272 return this;
273 }
274
275 binary_node(ElementType value = ElementType{}, binary_node* parent = nullptr):
276 m_value{value}, m_parent{parent} { }
277
278 // if insertion fails, returns false
279
280 template<typename Type>
281 // we enable this function only when Type and ElementType are same
283 insert(Type&& value)
284 {
285 if(value == this->m_value)
286 return false;
287 else if(value < this->m_value)
288 {
289 if(this->m_left)
290 // this is recursion
291 return this->m_left->insert(std::forward<Type>(value));
292 else
293 {
294 // a new node is inserted and set to this->m_left member
295 // new inserted node is a Leaf node.
296 this->m_left.reset(new binary_node{std::forward<Type>(value), this} );
297
298 // this call updates all m_height members of its parents
299 this->m_left->update_height();
300
301 return true;
302 }
303 }
304 else // value > this->m_value
305 {
306 if(this->m_right)
307 // this is also recursion
308 return this->m_right->insert(std::forward<Type>(value));
309 else
310 {
311 // a new node is inserted and set to this->m_right member
312 // the new inserted node is a LEAF node
313 this->m_right.reset( new binary_node{std::forward<Type>(value), this});
314
315 // update all m_height members of its parents
316 this->m_right->update_height();
317
318 return true;
319 }
320 }
321 }
322
323 // node_ptr_t == std::unique_ptr<binary_node>
324 bool graft(node_ptr_t& node_ptr)
325 {
326 if(node_ptr->m_value < this->m_value)
327 {
328 if(this->m_left)
329 // this is recursion
330 return this->m_left->graft(node_ptr);
331 else
332 {
333 node_ptr->m_parent = this;
334 this->m_left = std::move(node_ptr);
335 this->m_left->update_height();
336
337 return true;
338 }
339 }
340 else // node_ptr->m_value > this->m_value
341 {
342 if(this->m_right)
343 // this is also recursion
344 return this->m_right->graft(node_ptr);
345 else
346 {
347 node_ptr->m_parent = this;
348 this->m_right = std::move(node_ptr);
349 this->m_right->update_height();
350
351 return true;
352 }
353 }
354 }
355
356 // return true only if all parameters are inserted
357 // successfully, otherwise returns false
358 template<typename Type, typename... Types>
359 // we enable this function only when ElementType, Type, and Types... are
360 // of same type
361 enable_if_all_types_are_the_same_t<bool, ElementType, Type, Types...>
362 insert(Type&& arg, Types&&... args)
363 {
364 bool result = this->insert(std::forward<Type>(arg));
365
366 if constexpr(sizeof...(args) != 0)
367 {
368 // recursion
369 return result && this->insert(std::forward<Types>(args)...);
370 }
371 else
372 return result;
373 }
374
375 // for more information about visiting order
376 // Binary Tree (ALL Interview Questions)
377 // https://www.youtube.com/watch?v=VQTF_pRTZek&list=PLeIMaH7i8JDj7DnmO7lll97P1yZjMCpgY&index=2
379 {
380 switch(order)
381 {
383 {
384 os << this->m_value << ", ";
385
386 if(this->m_left)
387 this->m_left->visit_nodes(os, order);
388
389 if(this->m_right)
390 this->m_right->visit_nodes(os, order);
391
392 return;
393 }
395 {
396 if(this->m_left)
397 this->m_left->visit_nodes(os, order);
398
399 if(this->m_right)
400 this->m_right->visit_nodes(os, order);
401
402 os << this->m_value << ", ";
403
404 return;
405 }
406
408 {
409 if(this->m_right)
410 this->m_right->visit_nodes(os, order);
411
412 os << this->m_value << ", ";
413
414 if(this->m_left)
415 this->m_left->visit_nodes(os, order);
416
417 return;
418 }
419
421 default: // in_order
422 {
423 if(this->m_left)
424 this->m_left->visit_nodes(os, order);
425
426 os << this->m_value << ", ";
427
428 if(this->m_right)
429 this->m_right->visit_nodes(os, order);
430
431 return;
432 }
433 }
434 }
435
436 // if fails, return nullptr
437 binary_node* find(ElementType value, find_mode fmode,
439 {
440 binary_node* ptr = nullptr;
441
442 if(((vmode==visit_mode::ascending_order) && (fmode==find_mode::successor))||
444 {
445 auto ref_node = this->find(value);
446
447 if(ref_node)
448 {
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);
453
454 }
455
456 return nullptr;
457
458 }
459 else if(( (vmode == visit_mode::ascending_order)&&(fmode==find_mode::predecessor)) ||
461 {
462 auto ref_node = this->find(value);
463
464 if(ref_node)
465 {
466 if(ref_node->m_left)
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);
470 }
471
472 return nullptr;
473
474 }
475 else if(fmode == find_mode::exact_match)
476 return this->find(value);
477 else
478 return nullptr;
479 }
480
482 {
483 // both m_left and m_right are nullptr
484 return (!this->m_left && !this->m_right);
485 }
486
488 {
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);
493 else
494 return nullptr;
495 }
496
497 static bool remove_node(node_ptr_t& root_ptr, ElementType value)
498 {
499 binary_node* ptr = root_ptr->find(value);
500
501 // node with "value" does not exist
502 if(!ptr) return false;
503
504 // if parent is nullptr, then it is root node
505 if(!ptr->m_parent)
506 {
507 // ptr is a root node of type binary_node*
508 // root_ptr is a root node of type
509 // std::unique_ptr<binary_node>;
510
511 // we move left child to left_child
512 // after move, root_ptr->m_left is invalid
513 node_ptr_t left_child
514 = std::move(root_ptr->m_left);
515
516 // after move, root_ptr->m_right is invalid
517 node_ptr_t right_child
518 = std::move(root_ptr->m_right);
519
520 if(right_child) // new root
521 {
522 // because root node does not have its parent.
523 right_child->m_parent = nullptr;
524
525 // existing root_ptr is destroyed
526 // and right_child is moved to root_ptr
527 // at this point, existing old root is
528 // properly released.
529 root_ptr = std::move(right_child);
530
531 // do not forget this part
532 if(left_child)
533 root_ptr->graft(left_child);
534
535 return true;
536 }
537 else if(left_child) // right_child is nullptr
538 // left_child is a new root.
539 {
540 // because root node does not have its parent.
541 left_child->m_parent = nullptr;
542
543 // after move, the older root is released
544 // and left_child is moved to root_ptr
545 root_ptr = std::move(left_child);
546
547 return true;
548 }
549 else
550 {
551 // since we destroyed the root
552 // we should not access the root after this statment
553 root_ptr.reset();
554
555 return true;
556 }
557 }
558 else // non-root node
559 {
560 // ptr is the node to remove
561 // is not a root node.
562
563 if(ptr->is_leaf_node())
564 {
565 // this code cuts off the relation
566 // between the child node and its parent.
567 node_ptr_t orphan =
568 ptr->m_parent->release_child(ptr);
569
570 // when the orphan goes off this block,
571 // the allocated memory for orphan is
572 // cleaned up. and orphan.get() == ptr
573
574 if(ptr->m_parent->is_leaf_node())
575 {
576 ptr->m_parent->m_height = 1;
577 ptr->m_parent->update_height();
578 }
579
580 return true;
581 }
582 else // not a leaf node,
583 {
584 // cut off the relationship between ptr
585 // and its parent.
586 node_ptr_t orphan =
587 ptr->m_parent->release_child(ptr);
588
589 // this is for update the height of the parents
590 // nodes
591 ptr->m_parent->height(true);
592 ptr->m_parent->update_height();
593
594 node_ptr_t left_child =
595 std::move(orphan->m_left);
596
597 node_ptr_t right_child =
598 std::move(orphan->m_right);
599
600 if(right_child)
601 root_ptr->graft(right_child);
602
603 if(left_child)
604 root_ptr->graft(left_child);
605
606 return true;
607 }
608 }
609 }
610}; // end of binary_node class
611
612// std::unique_ptr<binary_node<ElementType>>
613template<typename ElementType>
615
616template<typename ElementType>
617void test_remove_node(node_ptr_t<ElementType>& node_ptr, ElementType value)
618{
619 using binary_node_t = binary_node<ElementType>;
620 using node_ptr_t = std::unique_ptr<binary_node_t>;
621
622 binary_node_t::remove_node(node_ptr, value);
623
624 if(node_ptr)
625 {
626 stream << node_ptr->build_digraph() << endl;
627 }
628
629}
630
632{
633 // In courtesy of Vivekanand Khyade - Algorithm Every Day
634 // Introduction to AVL tree (Why AVL tree is needed?)
635 // https://youtu.be/5Q-__zhQ2Gs?t=10
636
637 binary_node<int> root{10};
638
640
641 root.insert(8);
642 root.insert(15);
643
644 root.insert(7);
645 root.insert(9);
646 root.insert(12);
647 root.insert(17);
648
649 root.insert(6);
650 root.insert(16);
651 root.insert(18);
652
653 tpf::sstream os;
654
655 root.visit_nodes(os, visit_mode::ascending_order);
656 stream << "Ascending-order: " << endL;
657 stream << os.str() << endL;
658
659 os.clear();
660
661 root.visit_nodes(os, visit_mode::descending_order);
662 stream << "Descending-order: " << endL;
663 stream << os.str() << endL;
664}
665
667{
668 // In courtesy of Vivekanand Khyade - Algorithm Every Day
669 // Introduction to AVL tree (Why AVL tree is needed?)
670 // https://youtu.be/5Q-__zhQ2Gs?t=10
671
672 binary_node<int> root{10};
673
675
676 root.insert(8, 15, 7, 9, 12, 17, 6, 16, 18, 25);
677
678 if(auto ptr = root.find(6))
679 {
680 stream << "Value found: " << ptr->get() << endl;
681 }
682 else
683 {
684 stream <<"Value not found " << endl;
685 }
686
687 if(auto ptr = root.find(20) )
688 {
689 stream << "Value found: " << ptr->get() << endl;
690 }
691 else
692 {
693 stream << "Value not found " << endl;
694 }
695}
696
697
699{
700 // In courtesy of Vivekanand Khyade - Algorithm Every Day
701 // Introduction to AVL tree (Why AVL tree is needed?)
702 // https://youtu.be/5Q-__zhQ2Gs?t=10
703
704 binary_node<int> root{10};
705
707
708 root.insert(8, 15, 7, 9, 12, 17, 6, 16, 18);
709
710 stream << root.build_digraph() << endl;
711
712}
713
714void print_usage(string_t appname, const char* msg)
715{
716 stream << "Message: " << msg << endL;
717
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;
721
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;
724
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;
728
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;
732
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;
736
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;
740
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;
744}
745
746int main(int argc, const char* argv[])
747{
748 // test_ascending_descending_order();
749 // test_find_binary_tree();
750 // test_build_digraph();
751
752 string_t appname{argv[0]};
753
754 if(argc < 2)
755 {
756 print_usage(appname, "Program commandline syntax");
757
758 return 0;
759 }
760
761 string_t command{argv[1]};
762
763 if(command == "graph")
764 {
765 binary_node<int> root { std::atoi(argv[2])};
766
767 for(int i = 3; i < argc; ++i)
768 {
769 root.insert( std::atoi(argv[i]) );
770 }
771
772 stream << root.build_digraph() << endl;
773 }
774 else if(command == "list")
775 {
776 binary_node<int> root { std::atoi(argv[2])};
778
779 for(int i = 3; i < argc; ++i)
780 {
781 root.insert( std::atoi(argv[i]) );
782 }
783
784 stream <<"Ascending order: ";
785 root.visit_nodes(stream, visit_mode::ascending_order);
786 stream << endl;
787
788 stream <<"Descending order: ";
789 root.visit_nodes(stream, visit_mode::descending_order);
790 stream << endl;
791 }
792 else if(command == "ascending"
793 || command == "descending")
794 {
796 using find_mode = binary_node<int>::find_mode;
797
798 visit_mode vmode {visit_mode::undefined};
799 find_mode fmode {find_mode::undefined};
800
801 if(command == "ascending")
802 vmode = visit_mode::ascending_order;
803
804 if(command == "descending")
805 vmode = visit_mode::descending_order;
806
807 if(vmode==visit_mode::undefined)
808 {
809 print_usage(appname, "Undefined visit mode");
810 return 0;
811 }
812
813 if(argc < 5)
814 {
815 print_usage(appname, "Syntax Error");
816 return 0;
817 }
818
819 string_t operation{argv[2]};
820
821 if(operation == "successor_of")
822 fmode = find_mode::successor;
823
824 if(operation == "predecessor_of")
825 fmode = find_mode::predecessor;
826
827 if(operation == "exact_match_of")
828 fmode = find_mode::exact_match;
829
830 if(fmode == find_mode::undefined)
831 {
832 print_usage(appname, "Undefined find mode");
833 return 0;
834 }
835
836 int value = std::atoi(argv[3]);
837
838 binary_node<int> root { std::atoi(argv[4])};
840
841 for(int i = 5; i < argc; ++i)
842 {
843 root.insert( std::atoi(argv[i]) );
844 }
845
846 stream <<"Ascending order: ";
847 root.visit_nodes(stream, visit_mode::ascending_order);
848 stream << endl;
849
850 stream <<"Descending order: ";
851 root.visit_nodes(stream, visit_mode::descending_order);
852 stream << endl;
853
854 auto ptr = root.find(value, fmode, vmode);
855
856 if(ptr)
857 {
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;
864
865 if(vmode == visit_mode::ascending_order)
866 stream << " in ascending order is ";
867
868 if(vmode == visit_mode::descending_order)
869 stream << " in descending order is ";
870
871 stream << ptr->get() << endL;
872 }
873 else
874 {
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;
881
882 if(vmode == visit_mode::ascending_order)
883 stream << " in ascending order is NOT found";
884
885 if(vmode == visit_mode::descending_order)
886 stream << " in descending order NOT found ";
887
888 stream << endL;
889 }
890 }
891 else if(command == "remove")
892 {
893 using binary_node_t = binary_node<int>;
894 using node_ptr_t = std::unique_ptr<binary_node_t>;
895
896 // binary_tree remove 10 10
897 if(argc < 4)
898 {
899 print_usage(appname, "Syntax Error");
900 return 0;
901 }
902
903 int value = std::atoi(argv[2]);
904
905 node_ptr_t root = std::make_unique<binary_node_t>(std::atoi(argv[3]));
906
907 for(int i = 4; i < argc; ++i)
908 {
909 root->insert( std::atoi(argv[i]) );
910 }
911
912 test_remove_node(root, value);
913 }
914 else if(command == "find")
915 {
916 using binary_node_t = binary_node<int>;
917 using node_ptr_t = std::unique_ptr<binary_node_t>;
918
919 // binary_tree remove 10 10
920 if(argc < 4)
921 {
922 print_usage(appname, "Syntax Error");
923 return 0;
924 }
925
926 int value = std::atoi(argv[2]);
927
928 node_ptr_t root = std::make_unique<binary_node_t>(std::atoi(argv[3]));
929
930 for(int i = 4; i < argc; ++i)
931 {
932 root->insert( std::atoi(argv[i]) );
933 }
934
935 binary_node_t* ptr = root->find(value);
936
937 if(ptr)
938 {
939 stream << "We found value: " << value << endl;
940 }
941 else
942 {
943 stream << "We failed to find the value: " << value << endl;
944 }
945 }
946
947 else if(command == "nearest_parents")
948 {
949 using binary_node_t = binary_node<int>;
950 using node_ptr_t = std::unique_ptr<binary_node_t>;
951
952 // binary_tree remove 10 10
953 if(argc < 4)
954 {
955 print_usage(appname, "Syntax Error");
956 return 0;
957 }
958
959 int value = std::atoi(argv[2]);
960
961 node_ptr_t root = std::make_unique<binary_node_t>(std::atoi(argv[3]));
962
963 for(int i = 4; i < argc; ++i)
964 {
965 root->insert( std::atoi(argv[i]) );
966 }
967
968 auto left_parent_ptr = root->nearest_left_parent(value);
969 if(left_parent_ptr)
970 {
971 stream <<"The nearest left parent of the node "
972 << value << " is " << left_parent_ptr->get() << endl;
973 }
974 else
975 {
976 stream <<"The nearest left parent of the node "
977 << value << " is NOT foound." << endl;
978 }
979
980 auto right_parent_ptr = root->nearest_right_parent(value);
981 if(right_parent_ptr)
982 {
983 stream <<"The nearest right parent of the node "
984 << value << " is " << right_parent_ptr->get() << endl;
985 }
986 else
987 {
988 stream <<"The nearest right parent of the node "
989 << value << " is NOT foound." << endl;
990 }
991 }
992
993 else if(command == "min_max")
994 {
995 using binary_node_t = binary_node<int>;
996 using node_ptr_t = std::unique_ptr<binary_node_t>;
997
998 // binary_tree min_max 10 12
999 if(argc < 3)
1000 {
1001 print_usage(appname, "Syntax Error");
1002 return 0;
1003 }
1004
1005 node_ptr_t root = std::make_unique<binary_node_t>(std::atoi(argv[2]));
1006
1007 for(int i = 3; i < argc; ++i)
1008 {
1009 root->insert( std::atoi(argv[i]) );
1010 }
1011
1012 binary_node_t* ptr_min = root->minimum();
1013
1014 if(ptr_min)
1015 {
1016 stream << "We found minim value: " << ptr_min->get() << endl;
1017 }
1018 else
1019 {
1020 stream << "We failed to find minimum value " << endl;
1021 }
1022
1023
1024 binary_node_t* ptr_max = root->maximum();
1025
1026 if(ptr_min)
1027 {
1028 stream << "We found maximum value: " << ptr_max->get() << endl;
1029 }
1030 else
1031 {
1032 stream << "We failed to find maximum value " << endl;
1033 }
1034 }
1035}
std::string string_t
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
auto endL
tpf::sstream stream
auto nL
void test_remove_node(node_ptr_t< ElementType > &node_ptr, ElementType value)
void print_usage(string_t appname, const char *msg)
auto endl
void test_ascending_descending_order()
void test_find_binary_tree()
int main(int argc, const char *argv[])
auto nl
void test_build_digraph()
typename graph_t::visit_mode visit_mode
Definition: 060-graph02.cpp:8
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)
ElementType get() const
binary_node * nearest_right_parent(ElementType value)
binary_node * nearest_left_parent(ElementType value)
void nearest_right_parent_raw(binary_node *child)
string_t build_digraph()
const ElementType & get() const
node_ptr_t release_child(binary_node *ptr)
binary_node * maximum()
void print_node(tpf::sstream &os)
std::unique_ptr< binary_node > node_ptr_t
tpf::sstream & get_node_definition(tpf::sstream &os)
binary_node * minimum()
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)
std::string str() const
Definition: tpf_output.hpp:951
string_stream & clear()
Definition: tpf_output.hpp:916
constexpr auto endL
Definition: tpf_output.hpp:974
constexpr auto nL
Definition: tpf_output.hpp:972
constexpr auto endl
Definition: tpf_output.hpp:973
constexpr auto nl
Definition: tpf_output.hpp:971
Stream output operators << are implemented.