C++ Library Extensions 2022.12.09
To help learn modern C++ programming
050-binary_tree02.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
2
4
5auto endl = tpf::endl; // single carriage return and flush to console output
6auto endL = tpf::endL; // double carriage returns and flush to console output
7
8auto nl = tpf::nl; // single carriage return without flush
9auto nL = tpf::nL; // double carriage returns without flush
10
11using string_t = std::string;
12
13template<typename ElementType>
14class binary_node
15{
16 public:
17 using node_ptr_t = std::unique_ptr<binary_node>;
18 enum class visit_mode: int{ pre_order, in_order,
19 ascending_order = in_order, post_order, descending_order };
20
21 private:
22
23 ElementType m_value; // node's value
24
25 binary_node* m_parent; // pointer to point to the parent node
26
27 node_ptr_t m_left; // left child node
28 node_ptr_t m_right; // right child node
29
30 public:
31
33 {
34 os << "node_" << this->m_value;
35 return os;
36 }
37
39 {
40 // node_1 [ shape=box, label = " Root "] ;
41 get_node_name(os)
42 << " [ shape=oval, label = \" "
43 << this->m_value << " \"] ;";
44
45 return os;
46 }
47
49 {
51
52 // root -> left
53 if(this->m_left)
54 {
55 get_node_name(os) << " -> ";
56 this->m_left->get_node_name(os) << ";" << nl;
57
58 // recursion for left children
59 this->m_left->print_node(os);
60 }
61
62 // root -> right
63 if(this->m_right)
64 {
65 get_node_name(os) << " -> ";
66 this->m_right->get_node_name(os) << ";" << nl;
67
68 // recursion for right children
69 this->m_right->print_node(os);
70 }
71 }
73 {
74 tpf::sstream os;
75
76 os << "digraph G { " << nl;
77
78 print_node(os);
79
80 os <<"}";
81
82 return os.str();
83 }
84
85 ElementType get() const { return this->m_value; }
86
87 // if find() fails, returns nullptr,
88 // if successful, it returns the pointer that points
89 // to the node that has the value
90 binary_node* find(ElementType value)
91 {
92 if(value == this->m_value)
93 return this;
94
95 binary_node* ptr = nullptr;
96
97 // recursion
98 if(this->m_left && (ptr = this->m_left->find(value)))
99 return ptr;
100 // recursion
101 if(this->m_right && (ptr = this->m_right->find(value)))
102 return ptr;
103
104 return nullptr;
105 }
106
107 binary_node(ElementType value = ElementType{}, binary_node* parent = nullptr):
108 m_value{value}, m_parent{parent} { }
109
110 // if insertion fails,
111 // returns false
112 bool insert(ElementType value)
113 {
114 if(value == this->m_value)
115 return false;
116 else if(value < this->m_value)
117 {
118 if(this->m_left)
119 // this is recursion
120 return this->m_left->insert(value);
121 else
122 {
123 this->m_left.reset( new binary_node{value, this} );
124 return true;
125 }
126 }
127 else // value > this->m_value
128 {
129 if(this->m_right)
130 // this is also recursion
131 return this->m_right->insert(value);
132 else
133 {
134 this->m_right.reset( new binary_node{value, this});
135 return true;
136 }
137 }
138 }
139
140 // return true only if all parameters are inserted
141 // successfully, otherwise returns false
142 template<typename Type, typename... Types>
143 bool insert(Type arg, Types... args)
144 {
145 bool result = this->insert(arg);
146
147 if constexpr(sizeof...(args) != 0)
148 {
149 // recursion
150 return result && this->insert(args...);
151 }
152 else
153 return result;
154 }
155
156 // for more information about visiting order
157 // Binary Tree (ALL Interview Questions)
158 // https://www.youtube.com/watch?v=VQTF_pRTZek&list=PLeIMaH7i8JDj7DnmO7lll97P1yZjMCpgY&index=2
160 {
161 switch(order)
162 {
164 {
165 os << this->m_value << nl;
166
167 if(this->m_left)
168 this->m_left->visit_nodes(os, order);
169
170 if(this->m_right)
171 this->m_right->visit_nodes(os, order);
172
173 return;
174 }
176 {
177 if(this->m_left)
178 this->m_left->visit_nodes(os, order);
179
180 if(this->m_right)
181 this->m_right->visit_nodes(os, order);
182
183 os << this->m_value << nl;
184
185 return;
186 }
187
189 {
190 if(this->m_right)
191 this->m_right->visit_nodes(os, order);
192
193 os << this->m_value << nl;
194
195 if(this->m_left)
196 this->m_left->visit_nodes(os, order);
197
198 return;
199 }
200
202 default: // in_order
203 {
204 if(this->m_left)
205 this->m_left->visit_nodes(os, order);
206
207 os << this->m_value << nl;
208
209 if(this->m_right)
210 this->m_right->visit_nodes(os, order);
211
212 return;
213 }
214 }
215 }
216};
217
219{
220 // In courtesy of Vivekanand Khyade - Algorithm Every Day
221 // Introduction to AVL tree (Why AVL tree is needed?)
222 // https://youtu.be/5Q-__zhQ2Gs?t=10
223
224 binary_node<int> root{10};
225
227
228 root.insert(8);
229 root.insert(15);
230
231 root.insert(7);
232 root.insert(9);
233 root.insert(12);
234 root.insert(17);
235
236 root.insert(6);
237 root.insert(16);
238 root.insert(18);
239
240 tpf::sstream os;
241
242 root.visit_nodes(os, visit_mode::ascending_order);
243 stream << "Ascending-order: " << endL;
244 stream << os.str() << endL;
245
246 os.clear();
247
248 root.visit_nodes(os, visit_mode::descending_order);
249 stream << "Descending-order: " << endL;
250 stream << os.str() << endL;
251}
252
254{
255 // In courtesy of Vivekanand Khyade - Algorithm Every Day
256 // Introduction to AVL tree (Why AVL tree is needed?)
257 // https://youtu.be/5Q-__zhQ2Gs?t=10
258
259 binary_node<int> root{10};
260
262
263 root.insert(8, 15, 7, 9, 12, 17, 6, 16, 18, 25);
264
265 if(auto ptr = root.find(6))
266 {
267 stream << "Value found: " << ptr->get() << endl;
268 }
269 else
270 {
271 stream <<"Value not found " << endl;
272 }
273
274 if(auto ptr = root.find(20) )
275 {
276 stream << "Value found: " << ptr->get() << endl;
277 }
278 else
279 {
280 stream << "Value not found " << endl;
281 }
282}
283
284
286{
287 // In courtesy of Vivekanand Khyade - Algorithm Every Day
288 // Introduction to AVL tree (Why AVL tree is needed?)
289 // https://youtu.be/5Q-__zhQ2Gs?t=10
290
291 binary_node<int> root{10};
292
294
295 root.insert(8, 15, 7, 9, 12, 17, 6, 16, 18);
296
297 stream << root.build_digraph() << endl;
298
299}
300
301
302int main(int argc, const char* argv[])
303{
304 // test_ascending_descending_order();
305
306 // test_find_binary_tree();
307
308 // test_build_digraph();
309
310 if(argc < 2)
311 {
312 // Introduction to AVL tree (Why AVL tree is needed?)
313 //v https://youtu.be/5Q-__zhQ2Gs?t=29
314
315 // bin_graph 10 8 15 7 9 12 17 6 16 18 > binary_tree.gv
316
317 stream << "Usage: " << argv[0] << " node list " << endl;
318 stream <<"Example: "<<argv[0] <<" 10 8 15 7 9 12 17 6 16 18 > binary_tree.gv" << endl;
319 stream << "dot -Tpng binary_tree.gv -o binary_tree.png" << endl;
320
321 return 0;
322 }
323
324 binary_node<int> root { std::atoi(argv[1])};
325
326 for(int i = 2; i < argc; ++i)
327 {
328 root.insert( std::atoi(argv[i]) );
329 }
330
331 stream << root.build_digraph() << endl;
332}
std::string string_t
auto endL
tpf::sstream stream
auto nL
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 binary_node< ElementType >::node_ptr_t node_ptr_t
typename graph_t::visit_mode visit_mode
Definition: 060-graph02.cpp:8
bool insert(Type arg, Types... args)
binary_node * find(ElementType value)
tpf::sstream & get_node_name(tpf::sstream &os)
ElementType get() const
string_t build_digraph()
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(ElementType value=ElementType{}, binary_node *parent=nullptr)
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.