├── .gitattributes
├── .gitignore
├── BST ASCII Visualization.sln
├── BST ASCII Visualization
├── BST ASCII Visualization.vcxproj
├── BST ASCII Visualization.vcxproj.filters
├── bst.cpp
├── bst.h
├── node.cpp
├── node.h
├── source.cpp
├── visualizer.cpp
└── visualizer.h
├── LICENSE.md
├── README.md
└── STUDY_CASE.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | bld/
24 | [Bb]in/
25 | [Oo]bj/
26 | [Ll]og/
27 |
28 | # Visual Studio 2015/2017 cache/options directory
29 | .vs/
30 | # Uncomment if you have tasks that create the project's static files in wwwroot
31 | #wwwroot/
32 |
33 | # Visual Studio 2017 auto generated files
34 | Generated\ Files/
35 |
36 | # MSTest test Results
37 | [Tt]est[Rr]esult*/
38 | [Bb]uild[Ll]og.*
39 |
40 | # NUNIT
41 | *.VisualState.xml
42 | TestResult.xml
43 |
44 | # Build Results of an ATL Project
45 | [Dd]ebugPS/
46 | [Rr]eleasePS/
47 | dlldata.c
48 |
49 | # Benchmark Results
50 | BenchmarkDotNet.Artifacts/
51 |
52 | # .NET Core
53 | project.lock.json
54 | project.fragment.lock.json
55 | artifacts/
56 |
57 | # StyleCop
58 | StyleCopReport.xml
59 |
60 | # Files built by Visual Studio
61 | *_i.c
62 | *_p.c
63 | *_h.h
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.iobj
68 | *.pch
69 | *.pdb
70 | *.ipdb
71 | *.pgc
72 | *.pgd
73 | *.rsp
74 | *.sbr
75 | *.tlb
76 | *.tli
77 | *.tlh
78 | *.tmp
79 | *.tmp_proj
80 | *_wpftmp.csproj
81 | *.log
82 | *.vspscc
83 | *.vssscc
84 | .builds
85 | *.pidb
86 | *.svclog
87 | *.scc
88 |
89 | # Chutzpah Test files
90 | _Chutzpah*
91 |
92 | # Visual C++ cache files
93 | ipch/
94 | *.aps
95 | *.ncb
96 | *.opendb
97 | *.opensdf
98 | *.sdf
99 | *.cachefile
100 | *.VC.db
101 | *.VC.VC.opendb
102 |
103 | # Visual Studio profiler
104 | *.psess
105 | *.vsp
106 | *.vspx
107 | *.sap
108 |
109 | # Visual Studio Trace Files
110 | *.e2e
111 |
112 | # TFS 2012 Local Workspace
113 | $tf/
114 |
115 | # Guidance Automation Toolkit
116 | *.gpState
117 |
118 | # ReSharper is a .NET coding add-in
119 | _ReSharper*/
120 | *.[Rr]e[Ss]harper
121 | *.DotSettings.user
122 |
123 | # JustCode is a .NET coding add-in
124 | .JustCode
125 |
126 | # TeamCity is a build add-in
127 | _TeamCity*
128 |
129 | # DotCover is a Code Coverage Tool
130 | *.dotCover
131 |
132 | # AxoCover is a Code Coverage Tool
133 | .axoCover/*
134 | !.axoCover/settings.json
135 |
136 | # Visual Studio code coverage results
137 | *.coverage
138 | *.coveragexml
139 |
140 | # NCrunch
141 | _NCrunch_*
142 | .*crunch*.local.xml
143 | nCrunchTemp_*
144 |
145 | # MightyMoose
146 | *.mm.*
147 | AutoTest.Net/
148 |
149 | # Web workbench (sass)
150 | .sass-cache/
151 |
152 | # Installshield output folder
153 | [Ee]xpress/
154 |
155 | # DocProject is a documentation generator add-in
156 | DocProject/buildhelp/
157 | DocProject/Help/*.HxT
158 | DocProject/Help/*.HxC
159 | DocProject/Help/*.hhc
160 | DocProject/Help/*.hhk
161 | DocProject/Help/*.hhp
162 | DocProject/Help/Html2
163 | DocProject/Help/html
164 |
165 | # Click-Once directory
166 | publish/
167 |
168 | # Publish Web Output
169 | *.[Pp]ublish.xml
170 | *.azurePubxml
171 | # Note: Comment the next line if you want to checkin your web deploy settings,
172 | # but database connection strings (with potential passwords) will be unencrypted
173 | *.pubxml
174 | *.publishproj
175 |
176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
177 | # checkin your Azure Web App publish settings, but sensitive information contained
178 | # in these scripts will be unencrypted
179 | PublishScripts/
180 |
181 | # NuGet Packages
182 | *.nupkg
183 | # The packages folder can be ignored because of Package Restore
184 | **/[Pp]ackages/*
185 | # except build/, which is used as an MSBuild target.
186 | !**/[Pp]ackages/build/
187 | # Uncomment if necessary however generally it will be regenerated when needed
188 | #!**/[Pp]ackages/repositories.config
189 | # NuGet v3's project.json files produces more ignorable files
190 | *.nuget.props
191 | *.nuget.targets
192 |
193 | # Microsoft Azure Build Output
194 | csx/
195 | *.build.csdef
196 |
197 | # Microsoft Azure Emulator
198 | ecf/
199 | rcf/
200 |
201 | # Windows Store app package directories and files
202 | AppPackages/
203 | BundleArtifacts/
204 | Package.StoreAssociation.xml
205 | _pkginfo.txt
206 | *.appx
207 |
208 | # Visual Studio cache files
209 | # files ending in .cache can be ignored
210 | *.[Cc]ache
211 | # but keep track of directories ending in .cache
212 | !*.[Cc]ache/
213 |
214 | # Others
215 | ClientBin/
216 | ~$*
217 | *~
218 | *.dbmdl
219 | *.dbproj.schemaview
220 | *.jfm
221 | *.pfx
222 | *.publishsettings
223 | orleans.codegen.cs
224 |
225 | # Including strong name files can present a security risk
226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
227 | #*.snk
228 |
229 | # Since there are multiple workflows, uncomment next line to ignore bower_components
230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
231 | #bower_components/
232 |
233 | # RIA/Silverlight projects
234 | Generated_Code/
235 |
236 | # Backup & report files from converting an old project file
237 | # to a newer Visual Studio version. Backup files are not needed,
238 | # because we have git ;-)
239 | _UpgradeReport_Files/
240 | Backup*/
241 | UpgradeLog*.XML
242 | UpgradeLog*.htm
243 | ServiceFabricBackup/
244 | *.rptproj.bak
245 |
246 | # SQL Server files
247 | *.mdf
248 | *.ldf
249 | *.ndf
250 |
251 | # Business Intelligence projects
252 | *.rdl.data
253 | *.bim.layout
254 | *.bim_*.settings
255 | *.rptproj.rsuser
256 |
257 | # Microsoft Fakes
258 | FakesAssemblies/
259 |
260 | # GhostDoc plugin setting file
261 | *.GhostDoc.xml
262 |
263 | # Node.js Tools for Visual Studio
264 | .ntvs_analysis.dat
265 | node_modules/
266 |
267 | # Visual Studio 6 build log
268 | *.plg
269 |
270 | # Visual Studio 6 workspace options file
271 | *.opt
272 |
273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
274 | *.vbw
275 |
276 | # Visual Studio LightSwitch build output
277 | **/*.HTMLClient/GeneratedArtifacts
278 | **/*.DesktopClient/GeneratedArtifacts
279 | **/*.DesktopClient/ModelManifest.xml
280 | **/*.Server/GeneratedArtifacts
281 | **/*.Server/ModelManifest.xml
282 | _Pvt_Extensions
283 |
284 | # Paket dependency manager
285 | .paket/paket.exe
286 | paket-files/
287 |
288 | # FAKE - F# Make
289 | .fake/
290 |
291 | # JetBrains Rider
292 | .idea/
293 | *.sln.iml
294 |
295 | # CodeRush personal settings
296 | .cr/personal
297 |
298 | # Python Tools for Visual Studio (PTVS)
299 | __pycache__/
300 | *.pyc
301 |
302 | # Cake - Uncomment if you are using it
303 | # tools/**
304 | # !tools/packages.config
305 |
306 | # Tabs Studio
307 | *.tss
308 |
309 | # Telerik's JustMock configuration file
310 | *.jmconfig
311 |
312 | # BizTalk build output
313 | *.btp.cs
314 | *.btm.cs
315 | *.odx.cs
316 | *.xsd.cs
317 |
318 | # OpenCover UI analysis results
319 | OpenCover/
320 |
321 | # Azure Stream Analytics local run output
322 | ASALocalRun/
323 |
324 | # MSBuild Binary and Structured Log
325 | *.binlog
326 |
327 | # NVidia Nsight GPU debugger configuration file
328 | *.nvuser
329 |
330 | # MFractors (Xamarin productivity tool) working folder
331 | .mfractor/
332 |
333 | # Local History for Visual Studio
334 | .localhistory/
--------------------------------------------------------------------------------
/BST ASCII Visualization.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27004.2008
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BST ASCII Visualization", "BST ASCII Visualization\BST ASCII Visualization.vcxproj", "{99A0A558-8E0C-414C-9207-6E76E3C161B9}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {99A0A558-8E0C-414C-9207-6E76E3C161B9}.Debug|x64.ActiveCfg = Debug|x64
17 | {99A0A558-8E0C-414C-9207-6E76E3C161B9}.Debug|x64.Build.0 = Debug|x64
18 | {99A0A558-8E0C-414C-9207-6E76E3C161B9}.Debug|x86.ActiveCfg = Debug|Win32
19 | {99A0A558-8E0C-414C-9207-6E76E3C161B9}.Debug|x86.Build.0 = Debug|Win32
20 | {99A0A558-8E0C-414C-9207-6E76E3C161B9}.Release|x64.ActiveCfg = Release|x64
21 | {99A0A558-8E0C-414C-9207-6E76E3C161B9}.Release|x64.Build.0 = Release|x64
22 | {99A0A558-8E0C-414C-9207-6E76E3C161B9}.Release|x86.ActiveCfg = Release|Win32
23 | {99A0A558-8E0C-414C-9207-6E76E3C161B9}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {F4619FFB-7973-492B-9686-951170CB0C67}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/BST ASCII Visualization/BST ASCII Visualization.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 15.0
34 | {99A0A558-8E0C-414C-9207-6E76E3C161B9}
35 | BST
36 | 10.0.16299.0
37 |
38 |
39 |
40 | Application
41 | true
42 | v141
43 | MultiByte
44 |
45 |
46 | Application
47 | false
48 | v141
49 | true
50 | MultiByte
51 |
52 |
53 | Application
54 | true
55 | v141
56 | MultiByte
57 |
58 |
59 | Application
60 | false
61 | v141
62 | true
63 | MultiByte
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | Level3
87 | Disabled
88 | true
89 |
90 |
91 |
92 |
93 | Level3
94 | Disabled
95 | true
96 |
97 |
98 |
99 |
100 | Level3
101 | MaxSpeed
102 | true
103 | true
104 | true
105 |
106 |
107 | true
108 | true
109 |
110 |
111 |
112 |
113 | Level3
114 | MaxSpeed
115 | true
116 | true
117 | true
118 |
119 |
120 | true
121 | true
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/BST ASCII Visualization/BST ASCII Visualization.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 |
32 |
33 | Header Files
34 |
35 |
36 | Header Files
37 |
38 |
39 | Header Files
40 |
41 |
42 |
--------------------------------------------------------------------------------
/BST ASCII Visualization/bst.cpp:
--------------------------------------------------------------------------------
1 | #include "bst.h"
2 | #include "node.cpp"
3 | #include
4 | #include
5 | using namespace std;
6 |
7 |
8 | ////// Create Balanced Tree Helper Function //////
9 |
10 | template
11 | void bst::insert_middle_element(int start_index, int end_index, T* values, bst* balanced_tree)
12 | {
13 | // This function gets the middleIndex between startIndex and endIndex
14 | // then insert the elements at that index from the given array
15 | // to the given Binary Search Tree
16 |
17 | // Get the Number of elements between the startIndex and the endIndex
18 | const auto number_of_elements_in_between = end_index - start_index - 1;
19 |
20 | // If numberOfElementsInBetween is odd number
21 | // then we need to ceil the integer division
22 | // That's why a one is added before the division
23 |
24 | // e.g. if numberOfElementsInBetween is 3 (odd)
25 | // [ ] [ ] [ ] [S] [M] [ ] [ ] [E] --------> 3 / 2 = 1 + S
26 | // [ ] [ ] [ ] [S] [ ] [M] [ ] [E] --------> (3 + 1) / 2 = 2 + S (Desired output)
27 |
28 | // e.g. if numberOfElementsInBetween is 4 (even)
29 | // [ ] [ ] [ ] [S] [ ] [M] [ ] [ ] [E] ----> 4 / 2 = 2 + S
30 | // [ ] [ ] [ ] [S] [ ] [M] [ ] [ ] [E] ----> (4 + 1) / 2 = 2 + S (Desired output)
31 |
32 | auto middle_index = ((number_of_elements_in_between + 1) / 2) + start_index;
33 |
34 | if (number_of_elements_in_between < 0)
35 | {
36 | // In case startIndex equals endIndex
37 | balanced_tree->insert(values[start_index]);
38 | }
39 | else if (number_of_elements_in_between == 0)
40 | {
41 | // In case there is no elements between startIndex and endIndex
42 | balanced_tree->insert(values[start_index]);
43 | balanced_tree->insert(values[end_index]);
44 | }
45 | else
46 | {
47 | // In case there is more then one element between startIndex and endIndex
48 | balanced_tree->insert(values[middle_index]);
49 | // Slice the array into two parts and repeat the previous function on each part
50 | // First part starts from startIndex to the element before the middleIndex
51 | insert_middle_element(start_index, middle_index - 1, values, balanced_tree);
52 | // Second part starts from the element after the middleIndex to the endIndex
53 | insert_middle_element(middle_index + 1, end_index, values, balanced_tree);
54 | }
55 | }
56 |
57 |
58 | ////// Create Balanced Tree Function //////
59 |
60 | template
61 | bst bst::create_balanced_tree(T* values, int array_size)
62 | {
63 | // Takes an array of elements and its size then inserts
64 | // those elements to an initially Empty tree making sure that
65 | // the resulting tree is balanced, then returns the new tree.
66 | // (WARNING: ORIGINAL TREE WILL BE LOST!)
67 |
68 | // STEP 0: Create an empty tree
69 | bst balanced_tree;
70 |
71 | // STEP 1: Sort the given array in ascending order
72 | sort(values, values + array_size);
73 |
74 | // STEP 2: Insert Middle elements to the created tree
75 | insert_middle_element(0, array_size - 1, values, &balanced_tree);
76 |
77 | return balanced_tree;
78 | }
79 |
80 |
81 | ////// Remove Helper Functions //////
82 |
83 | template
84 | node* bst::find_min(node* start)
85 | {
86 | node* min_node = start;
87 | while (min_node->get_left() != nullptr)
88 | min_node = min_node->get_left();
89 | return min_node;
90 | }
91 |
92 | template
93 | node* bst::find_parent(T value)
94 | {
95 | node* first = root_;
96 | node* second = nullptr;
97 |
98 | while (first != nullptr && first->get_value() != value)
99 | {
100 | second = first;
101 | if (first->get_value() > value)
102 | first = first->get_left();
103 | else
104 | first = first->get_right();
105 | }
106 | return second;
107 | }
108 |
109 |
110 | ////// Main Functions //////
111 |
112 | template
113 | node* bst::get_root()
114 | {
115 | return root_;
116 | }
117 |
118 | template
119 | bool bst::contains(T value)
120 | {
121 | node* temp = find_node(value);
122 | return (temp != nullptr);
123 | }
124 |
125 | template
126 | node* bst::find_node(T value)
127 | {
128 | node* temp = root_;
129 |
130 | while (temp != nullptr && temp->get_value() != value)
131 | if (temp->get_value() > value)
132 | temp = temp->get_left();
133 | else
134 | temp = temp->get_right();
135 |
136 | return temp;
137 | }
138 |
139 | template
140 | void bst::insert(T value)
141 | {
142 | assert(!contains(value));
143 |
144 | auto* new_node = new node(value);
145 |
146 | if (root_ == nullptr)
147 | {
148 | root_ = new_node;
149 | return;
150 | }
151 |
152 | node* temp = root_;
153 | while (temp != nullptr)
154 | {
155 | if (temp->get_value() > value)
156 | {
157 | if (temp->get_left() == nullptr)
158 | {
159 | temp->set_left(new_node);
160 | break;
161 | }
162 | temp = temp->get_left();
163 | }
164 | else if (temp->get_right() == nullptr)
165 | {
166 | temp->set_right(new_node);
167 | break;
168 | }
169 | else
170 | temp = temp->get_right();
171 | }
172 | }
173 |
174 | template
175 | void bst::remove(T value)
176 | {
177 | node* del_node = find_node(value);
178 |
179 | if (del_node == nullptr)
180 | {
181 | cout << "Node does not exist! Cannot remove node." << endl;
182 | return;
183 | }
184 |
185 | if (del_node->get_left() == nullptr && del_node->get_right() == nullptr) // Deleting a leaf node
186 | {
187 | node* parent = find_parent(value);
188 | if (del_node == root_)
189 | root_ = nullptr;
190 | else
191 | {
192 | if (value < parent->get_value())
193 | parent->get_left() = nullptr;
194 | else
195 | parent->get_right() = nullptr;
196 | }
197 | delete del_node;
198 | }
199 | else if (del_node->get_left() == nullptr && del_node->get_right() != nullptr)
200 | {
201 | node* parent = find_parent(value);
202 | if (del_node == root_)
203 | root_ = del_node->get_right();
204 | else
205 | {
206 | if (value < parent->get_value())
207 | parent->get_left() = del_node->get_right();
208 | else
209 | parent->get_right() = del_node->get_right();
210 | }
211 | delete del_node;
212 | }
213 | else if (del_node->get_left() != nullptr && del_node->get_right() == nullptr)
214 | {
215 | node* parent = find_parent(value);
216 | if (del_node == root_)
217 | root_ = del_node->get_left();
218 | else
219 | {
220 | if (value < parent->get_value())
221 | parent->get_left() = del_node->get_left();
222 | else
223 | parent->get_right() = del_node->get_left();
224 | }
225 | delete del_node;
226 | }
227 | else
228 | {
229 | node* min_node = find_min(del_node->get_right());
230 | node* parent = find_parent(min_node->get_value());
231 | del_node->get_value() = min_node->get_value();
232 |
233 | if (parent == del_node)
234 | parent->get_right() = min_node->get_right();
235 | else
236 | parent->get_left() = min_node->get_right();
237 | delete min_node;
238 | }
239 | }
240 |
241 |
242 | ////// Display Functions //////
243 |
244 | template
245 | void bst::traverse(const int order)
246 | {
247 | switch (order)
248 | {
249 | case 1:
250 | in_order(root_);
251 | break;
252 | case 2:
253 | pre_order(root_);
254 | break;
255 | case 3:
256 | post_order(root_);
257 | break;
258 | default:
259 | cout << "Invalid traverse order!";
260 | }
261 | }
262 |
263 | template
264 | void bst::in_order(node* start)
265 | {
266 | if (start != nullptr)
267 | {
268 | in_order(start->get_left());
269 | cout << start->get_value() << endl;
270 | in_order(start->get_right());
271 | }
272 | }
273 |
274 | template
275 | void bst::pre_order(node* start)
276 | {
277 | if (start != nullptr)
278 | {
279 | cout << start->get_value() << endl;
280 | pre_order(start->get_left());
281 | pre_order(start->get_right());
282 | }
283 | }
284 |
285 | template
286 | void bst::post_order(node* start)
287 | {
288 | if (start != nullptr)
289 | {
290 | post_order(start->get_left());
291 | post_order(start->get_right());
292 | cout << start->get_value() << endl;
293 | }
294 | }
295 |
296 |
297 | ////// Count Function //////
298 |
299 | template
300 | int bst::count_nodes(node* start)
301 | {
302 | if (start == nullptr) return 0;
303 |
304 | auto counter = 1;
305 | if (start->get_left() != nullptr) counter += count_nodes(start->get_left());
306 | if (start->get_right() != nullptr) counter += count_nodes(start->get_right());
307 |
308 | return counter;
309 | }
--------------------------------------------------------------------------------
/BST ASCII Visualization/bst.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "node.h"
3 |
4 | template
5 | class bst
6 | {
7 | node* root_ = nullptr;
8 |
9 | // Create Balanced Tree Helper Function
10 | void insert_middle_element(int, int, T*, bst*);
11 |
12 | // Remove Helper Functions
13 | node* find_min(node*);
14 | node* find_parent(T);
15 |
16 | public:
17 |
18 | bst() = default;
19 | ~bst() = default;
20 |
21 | // Create Balanced Tree Function
22 | bst create_balanced_tree(T*, int);
23 |
24 | // Main Functions
25 | node* get_root();
26 | bool contains(T);
27 | node* find_node(T);
28 | void insert(T);
29 | void remove(T);
30 |
31 | // Display Functions
32 | void traverse(int);
33 | void in_order(node*);
34 | void pre_order(node*);
35 | void post_order(node*);
36 |
37 | // Count Function
38 | int count_nodes(node*);
39 |
40 | };
41 |
42 |
--------------------------------------------------------------------------------
/BST ASCII Visualization/node.cpp:
--------------------------------------------------------------------------------
1 | #include "node.h"
2 |
3 | template
4 | node::node()
5 | {
6 | left_ = right_ = nullptr;
7 | }
8 |
9 | template
10 | node::node(T value)
11 | {
12 | value_ = value;
13 | left_ = right_ = nullptr;
14 | }
15 |
16 | template
17 | T node::get_value()
18 | {
19 | return value_;
20 | }
21 |
22 | template
23 | node* node::get_left()
24 | {
25 | return left_;
26 | }
27 |
28 | template
29 | node* node::get_right()
30 | {
31 | return right_;
32 | }
33 |
34 | template
35 | void node::set_left(node* node)
36 | {
37 | left_ = node;
38 | }
39 |
40 | template
41 | void node::set_right(node* node)
42 | {
43 | right_ = node;
44 | }
45 |
--------------------------------------------------------------------------------
/BST ASCII Visualization/node.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | template
4 | class node
5 | {
6 | T value_;
7 | node* left_;
8 | node* right_;
9 |
10 | public:
11 | node();
12 | explicit node(T);
13 | T get_value();
14 | node* get_left();
15 | node* get_right();
16 | void set_left(node*);
17 | void set_right(node*);
18 | };
--------------------------------------------------------------------------------
/BST ASCII Visualization/source.cpp:
--------------------------------------------------------------------------------
1 | #include "bst.cpp"
2 | #include "visualizer.cpp"
3 | #include
4 | #include
5 |
6 | using namespace std;
7 |
8 | int main()
9 | {
10 | SetConsoleTitle("BST ASCII Visualization");
11 |
12 | // Initialize Array
13 | int arr[] = { 10, 7, 9, 6, 1, 19, 20, 21, 22, 23, 8, 11, 2, 0, 28, 29,
14 | 4, 5, 3, 12, 13, 14, 15, 16, 17, 18, 24, 25, 26, 27, 30 };
15 |
16 | // Get Array size
17 | const int arr_size = sizeof arr / sizeof arr[0];
18 |
19 | // Create a balanced tree from the previous array
20 | bst tree;
21 | tree = tree.create_balanced_tree(arr, arr_size);
22 |
23 | // Visualize the resulting tree
24 | const visualizer v(tree);
25 | cout << endl << endl;
26 | v.visualize();
27 | cout << endl << endl;
28 |
29 | system("Pause");
30 | return 0;
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/BST ASCII Visualization/visualizer.cpp:
--------------------------------------------------------------------------------
1 | #include "visualizer.h"
2 | #include
3 | #include
4 |
5 | template
6 | visualizer::visualizer(bst tree, int node_length /* = -1 */, int space_length /* = -1 */)
7 | {
8 |
9 | auto min_node_len = 0;
10 | auto min_space_len = 0;
11 |
12 | // Initialize tree-related variables
13 | tree_ = tree;
14 | tree_root_ = tree_.get_root();
15 | tree_height_ = get_tree_height(tree_root_);
16 | tree_nodes_ = get_nodes_count(tree_height_) - 1;
17 | queue*> nodes = breadth_first_search();
18 |
19 | // Initialize values_ array
20 | values_ = new string*[tree_nodes_];
21 | for (auto level = 0; level < tree_height_; level++)
22 | {
23 | values_[level] = new string[get_nodes_count(level)];
24 | for (auto node = 0; node < get_nodes_count(level); node++)
25 | {
26 | // Convert node to string and add it to values vector
27 | // also add empty string if node is empty
28 | auto value = nodes.front() == nullptr ? "" : to_string(nodes.front()->get_value());
29 | values_[level][node] = value;
30 | nodes.pop();
31 |
32 | // Calculate minimum required node length
33 | const int length = value.length();
34 | if (min_node_len < length) min_node_len = length;
35 | }
36 | }
37 |
38 | // Initialize node-related variables
39 | node_length_ = node_length > min_node_len ? node_length : min_node_len; // Choose suitable node length
40 | node_type_ = node_length_ % 2; // ZERO if length is even and ONE if odd
41 | node_shift_factor_ = node_length_ / 2; // Shifting factor used in visualizing
42 | empty_node_ = string(node_length_, ' '); // Represents an empty node
43 |
44 | // Initialize space-related variables
45 | min_space_len = node_type_ ? 3 : 4; // Calculate minimum required space length
46 | space_length_ = space_length > min_space_len ? space_length : min_space_len; // Choose suitable node length
47 | space_shift_factor_ = space_length_ / 2; // Shifting factor used in visualizing
48 |
49 | // Make sure that that both values are either even or odd
50 | assert(node_type_ == space_length_ % 2);
51 | }
52 |
53 | template
54 | queue*> visualizer::breadth_first_search()
55 | {
56 | queue*> temp, nodes;
57 | temp.push(tree_root_);
58 |
59 | for (auto i = 0; i < tree_nodes_; i++)
60 | {
61 | node* current = temp.front();
62 | temp.pop();
63 | nodes.push(current);
64 |
65 | if (current == nullptr)
66 | {
67 | temp.push(nullptr);
68 | temp.push(nullptr);
69 | }
70 | else
71 | {
72 | temp.push(current->get_left());
73 | temp.push(current->get_right());
74 | }
75 | }
76 |
77 | return nodes;
78 | }
79 |
80 | template
81 | int visualizer::get_tree_height(node* root) const
82 | {
83 | if (root == nullptr) return 0;
84 | const int left_height = get_tree_height(root->get_left());
85 | const int right_height = get_tree_height(root->get_right());
86 | return left_height > right_height ? left_height + 1 : right_height + 1;
87 | }
88 |
89 | template
90 | int visualizer::get_nodes_count(const int level) const
91 | {
92 | return int(pow(2, level));
93 | }
94 |
95 | template
96 | int visualizer::get_subtree_width(const int level) const
97 | {
98 | const auto levels_below = tree_height_ - level - 1;
99 | const auto nodes_count = get_nodes_count(levels_below);
100 | const auto spaces_count = nodes_count - 1;
101 | return node_length_ * nodes_count + space_length_ * spaces_count;
102 | }
103 |
104 | template
105 | void visualizer::visualize() const
106 | {
107 |
108 | const auto last_level = tree_height_ - 1;
109 |
110 | for (auto level = 0; level < tree_height_; level++)
111 | {
112 | const auto nodes_count = get_nodes_count(level);
113 | const auto last_node = nodes_count - 1;
114 | const auto subtree_width = get_subtree_width(level);
115 | const auto node_indentation = subtree_width / 2 - node_shift_factor_;
116 | const auto nodes_spacing = subtree_width - 2 * (node_shift_factor_ - space_shift_factor_);
117 | const auto branch_height = (subtree_width + 1) / 4;
118 |
119 | cout << string(node_indentation, ' ');
120 |
121 | for (auto node = 0; node < nodes_count; node++)
122 | {
123 | const auto node_value = values_[level][node].empty() ? empty_node_ : values_[level][node];
124 | cout << setw(node_length_) << setfill('0') << node_value;
125 | cout << string(nodes_spacing * (node != last_node), ' ');
126 | }
127 |
128 | cout << endl;
129 |
130 | for (auto i = 0; i < branch_height && level != last_level; i++)
131 | {
132 | const auto branch_indentation = subtree_width / 2 - 1 - i;
133 | cout << string(branch_indentation, ' ');
134 |
135 | for (auto node = 0; node < nodes_count; node++)
136 | {
137 | const auto has_left_child = !values_[level + 1][2 * node ].empty();
138 | const auto has_right_child = !values_[level + 1][2 * node + 1].empty();
139 | const auto branch_width = node_type_ + 2 * i;
140 | const auto branches_spacing = nodes_spacing + 2 * (node_shift_factor_ - 1 - i);
141 |
142 | cout << (has_left_child ? '/' : ' ');
143 | cout << string(branch_width, ' ');
144 | cout << (has_right_child ? '\\' : ' ');
145 | cout << string(branches_spacing * (node != last_node), ' ');
146 | }
147 |
148 | cout << endl;
149 | }
150 | }
151 |
152 | }
153 |
--------------------------------------------------------------------------------
/BST ASCII Visualization/visualizer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "bst.h"
3 | #include "node.h"
4 | #include
5 | #include
6 | using namespace std;
7 |
8 | template
9 | class visualizer
10 | {
11 |
12 | bst tree_;
13 | node* tree_root_;
14 | int tree_height_;
15 | int tree_nodes_;
16 | string** values_;
17 |
18 | int node_length_;
19 | int node_type_;
20 | int node_shift_factor_;
21 | string empty_node_;
22 |
23 | int space_length_;
24 | int space_shift_factor_;
25 |
26 | queue*> breadth_first_search();
27 | int get_tree_height(node*) const;
28 | int get_nodes_count(int) const;
29 | int get_subtree_width(int) const;
30 |
31 | public:
32 |
33 | explicit visualizer(bst, int = -1, int = -1);
34 | ~visualizer() = default;
35 | void visualize() const;
36 |
37 | };
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Youssef Raafat Nasry
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BST ASCII Visualization
2 |
3 | This program helps to Visualize [**Binary Search Trees**](https://en.wikipedia.org/wiki/Binary_search_tree) using **ASCII** characters with the [**Adaptive Node Length with Fixed Space Length Algorithm**](https://github.com/YoussefRaafatNasry/bst-ascii-visualization/blob/master/STUDY_CASE.md#iii-adaptive-node-length-with-fixed-space-length-algorithm) — _see my [**Study Case**](https://github.com/YoussefRaafatNasry/bst-ascii-visualization/blob/master/STUDY_CASE.md) for more info_.
4 |
5 | 
6 |
--------------------------------------------------------------------------------
/STUDY_CASE.md:
--------------------------------------------------------------------------------
1 | # Binary Search Tree Visualization Study Case
2 |
3 |
4 |
5 | [**I. Fixed Node/Space Length Algorithm**](#i-fixed-nodespace-length-algorithm)
6 |
7 | - [fixed-3-char-length Tree](#fixed-3-char-length-tree)
8 |
9 | [**II. Matching Adaptive Node/Space Length Algorithm**](#ii-matching-adaptive-nodespace-length-algorithm)
10 |
11 | - [1-char-length Tree (~~bugged~~)](#1-char-length-tree-bugged)
12 | - [2-char-length Tree](#2-char-length-tree)
13 | - [3-char-length Tree](#3-char-length-tree)
14 | - [4-char-length Tree](#4-char-length-tree)
15 | - [5-char-length Tree](#5-char-length-tree)
16 |
17 | [**III. Adaptive Node Length with Fixed Space Length Algorithm**](#iii-adaptive-node-length-with-fixed-space-length-algorithm)
18 |
19 | - [1-char-length-node + fixed-3-char-length-space Tree](#1-char-length-node--fixed-3-char-length-space-tree)
20 | - [2-char-length-node + fixed-4-char-length-space Tree](#2-char-length-node--fixed-4-char-length-space-tree)
21 | - [3-char-length-node + fixed-3-char-length-space Tree](#3-char-length-node--fixed-3-char-length-space-tree)
22 | - [4-char-length-node + fixed-4-char-length-space Tree](#4-char-length-node--fixed-4-char-length-space-tree)
23 | - [5-char-length-node + fixed-3-char-length-space Tree](#5-char-length-node--fixed-3-char-length-space-tree)
24 | - [6-char-length-node + fixed-4-char-length-space Tree](#6-char-length-node--fixed-4-char-length-space-tree)
25 | - [7-char-length-node + fixed-3-char-length-space Tree](#7-char-length-node--fixed-3-char-length-space-tree)
26 |
27 | [**IV. Hybrid Algorithm**](#iv-hybrid-algorithm)
28 |
29 | - [Hybrid Trees](#hybrid-trees)
30 |
31 |
32 |
33 | ---
34 |
35 | ## I. Fixed Node/Space Length Algorithm
36 |
37 | - Set both nodes' and spaces' lengths to a Fixed value (3 chars for example).
38 |
39 | | Advantages | Disadvantages |
40 | | :-- | :-- |
41 | | | Nodes with large values won't be displayed properly |
42 | | | Nodes' and spaces' lengths should be either even or odd but not both |
43 |
44 | ### fixed-3-char-length Tree
45 |
46 | ```shell
47 |
48 | 0X0
49 | / \
50 | / \
51 | / \
52 | / \
53 | / \
54 | / \
55 | / \
56 | / \
57 | / \
58 | / \
59 | / \
60 | 0X0 0X0
61 | / \ / \
62 | / \ / \
63 | / \ / \
64 | / \ / \
65 | / \ / \
66 | 0X0 0X0 0X0 0X0
67 | / \ / \ / \ / \
68 | / \ / \ / \ / \
69 | 0X0 0X0 0X0 0X0 0X0 0X0 0X0 0X0
70 |
71 | ```
72 |
73 | ## II. Matching Adaptive Node/Space Length Algorithm
74 |
75 | - Set both nodes' and spaces' lengths to the maximum node value's length.
76 |
77 | | Advantages | Disadvantages |
78 | | :-- | :-- |
79 | | Visually symmetric | 1-char-length node/space trees are bugged |
80 | | Node length is adaptive | Trees' width/height is too big |
81 | | | Consecutive even-length trees and odd-length trees have different heights |
82 | | | Nodes' and spaces' lengths should be either even or odd but not both |
83 |
84 |
85 |
86 | ### 1-char-length Tree (~~bugged~~)
87 |
88 | ```shell
89 |
90 | X
91 | / \
92 | / \
93 | / \
94 | X X
95 | / \ / \
96 | X X X X
97 | X X X X X X X X
98 |
99 | ```
100 |
101 | ### 2-char-length Tree
102 |
103 | ```shell
104 |
105 | XX
106 | /\
107 | / \
108 | / \
109 | / \
110 | / \
111 | / \
112 | / \
113 | XX XX
114 | /\ /\
115 | / \ / \
116 | / \ / \
117 | XX XX XX XX
118 | /\ /\ /\ /\
119 | XX XX XX XX XX XX XX XX
120 |
121 | ```
122 |
123 | ### 3-char-length Tree
124 |
125 | ```shell
126 |
127 | 0X0
128 | / \
129 | / \
130 | / \
131 | / \
132 | / \
133 | / \
134 | / \
135 | / \
136 | / \
137 | / \
138 | / \
139 | 0X0 0X0
140 | / \ / \
141 | / \ / \
142 | / \ / \
143 | / \ / \
144 | / \ / \
145 | 0X0 0X0 0X0 0X0
146 | / \ / \ / \ / \
147 | / \ / \ / \ / \
148 | 0X0 0X0 0X0 0X0 0X0 0X0 0X0 0X0
149 |
150 | ```
151 |
152 | ### 4-char-length Tree
153 |
154 | ```shell
155 |
156 | 0XX0
157 | /\
158 | / \
159 | / \
160 | / \
161 | / \
162 | / \
163 | / \
164 | / \
165 | / \
166 | / \
167 | / \
168 | / \
169 | / \
170 | / \
171 | / \
172 | 0XX0 0XX0
173 | /\ /\
174 | / \ / \
175 | / \ / \
176 | / \ / \
177 | / \ / \
178 | / \ / \
179 | / \ / \
180 | 0XX0 0XX0 0XX0 0XX0
181 | /\ /\ /\ /\
182 | / \ / \ / \ / \
183 | / \ / \ / \ / \
184 | 0XX0 0XX0 0XX0 0XX0 0XX0 0XX0 0XX0 0XX0
185 |
186 | ```
187 |
188 | ### 5-char-length Tree
189 |
190 | ```shell
191 |
192 | 00X00
193 | / \
194 | / \
195 | / \
196 | / \
197 | / \
198 | / \
199 | / \
200 | / \
201 | / \
202 | / \
203 | / \
204 | / \
205 | / \
206 | / \
207 | / \
208 | / \
209 | / \
210 | / \
211 | / \
212 | 00X00 00X00
213 | / \ / \
214 | / \ / \
215 | / \ / \
216 | / \ / \
217 | / \ / \
218 | / \ / \
219 | / \ / \
220 | / \ / \
221 | / \ / \
222 | 00X00 00X00 00X00 00X00
223 | / \ / \ / \ / \
224 | / \ / \ / \ / \
225 | / \ / \ / \ / \
226 | / \ / \ / \ / \
227 | 00X00 00X00 00X00 00X00 00X00 00X00 00X00 00X00
228 |
229 | ```
230 |
231 | ## III. Adaptive Node Length with Fixed Space Length Algorithm
232 |
233 | - Set spaces' length to **3 chars** in case node length is odd.
234 | - Set spaces' length to **4 chars** in case node length is even.
235 | - Set nodes' length to the maximum node value's length.
236 |
237 | | Advantages | Disadvantages |
238 | | :-- | :-- |
239 | | Node length is adaptive | Spacing between long-length-leaves is visually low |
240 | | Trees' width/height is smaller than Matching Node/Space length Trees | Nodes' and spaces' lengths should be either even or odd but not both |
241 | | 1-char-node-length trees aren't bugged | |
242 | | Consecutive even-length trees and odd-length trees have same height | |
243 |
244 | ### 1-char-length-node + fixed-3-char-length-space Tree
245 |
246 | ```shell
247 |
248 | X
249 | / \
250 | / \
251 | / \
252 | / \
253 | / \
254 | / \
255 | / \
256 | X X
257 | / \ / \
258 | / \ / \
259 | / \ / \
260 | X X X X
261 | / \ / \ / \ / \
262 | X X X X X X X X
263 |
264 | ```
265 |
266 | ### 2-char-length-node + fixed-4-char-length-space Tree
267 |
268 | ```shell
269 |
270 | XX
271 | /\
272 | / \
273 | / \
274 | / \
275 | / \
276 | / \
277 | / \
278 | / \
279 | / \
280 | / \
281 | / \
282 | XX XX
283 | /\ /\
284 | / \ / \
285 | / \ / \
286 | / \ / \
287 | / \ / \
288 | XX XX XX XX
289 | /\ /\ /\ /\
290 | / \ / \ / \ / \
291 | XX XX XX XX XX XX XX XX
292 |
293 | ```
294 |
295 | ### 3-char-length-node + fixed-3-char-length-space Tree
296 |
297 | ```shell
298 |
299 | 0X0
300 | / \
301 | / \
302 | / \
303 | / \
304 | / \
305 | / \
306 | / \
307 | / \
308 | / \
309 | / \
310 | / \
311 | 0X0 0X0
312 | / \ / \
313 | / \ / \
314 | / \ / \
315 | / \ / \
316 | / \ / \
317 | 0X0 0X0 0X0 0X0
318 | / \ / \ / \ / \
319 | / \ / \ / \ / \
320 | 0X0 0X0 0X0 0X0 0X0 0X0 0X0 0X0
321 |
322 | ```
323 |
324 | ### 4-char-length-node + fixed-4-char-length-space Tree
325 |
326 | ```shell
327 |
328 | 0XX0
329 | /\
330 | / \
331 | / \
332 | / \
333 | / \
334 | / \
335 | / \
336 | / \
337 | / \
338 | / \
339 | / \
340 | / \
341 | / \
342 | / \
343 | / \
344 | 0XX0 0XX0
345 | /\ /\
346 | / \ / \
347 | / \ / \
348 | / \ / \
349 | / \ / \
350 | / \ / \
351 | / \ / \
352 | 0XX0 0XX0 0XX0 0XX0
353 | /\ /\ /\ /\
354 | / \ / \ / \ / \
355 | / \ / \ / \ / \
356 | 0XX0 0XX0 0XX0 0XX0 0XX0 0XX0 0XX0 0XX0
357 |
358 | ```
359 |
360 | ### 5-char-length-node + fixed-3-char-length-space Tree
361 |
362 | ```shell
363 |
364 | 00X00
365 | / \
366 | / \
367 | / \
368 | / \
369 | / \
370 | / \
371 | / \
372 | / \
373 | / \
374 | / \
375 | / \
376 | / \
377 | / \
378 | / \
379 | / \
380 | 00X00 00X00
381 | / \ / \
382 | / \ / \
383 | / \ / \
384 | / \ / \
385 | / \ / \
386 | / \ / \
387 | / \ / \
388 | 00X00 00X00 00X00 00X00
389 | / \ / \ / \ / \
390 | / \ / \ / \ / \
391 | / \ / \ / \ / \
392 | 00X00 00X00 00X00 00X00 00X00 00X00 00X00 00X00
393 |
394 | ```
395 |
396 | ### 6-char-length-node + fixed-4-char-length-space Tree
397 |
398 | ```shell
399 |
400 | 00XX00
401 | /\
402 | / \
403 | / \
404 | / \
405 | / \
406 | / \
407 | / \
408 | / \
409 | / \
410 | / \
411 | / \
412 | / \
413 | / \
414 | / \
415 | / \
416 | / \
417 | / \
418 | / \
419 | / \
420 | 00XX00 00XX00
421 | /\ /\
422 | / \ / \
423 | / \ / \
424 | / \ / \
425 | / \ / \
426 | / \ / \
427 | / \ / \
428 | / \ / \
429 | / \ / \
430 | 00XX00 00XX00 00XX00 00XX00
431 | /\ /\ /\ /\
432 | / \ / \ / \ / \
433 | / \ / \ / \ / \
434 | / \ / \ / \ / \
435 | 00XX00 00XX00 00XX00 00XX00 00XX00 00XX00 00XX00 00XX00
436 |
437 | ```
438 |
439 | ### 7-char-length-node + fixed-3-char-length-space Tree
440 |
441 | ```shell
442 |
443 | 000X000
444 | / \
445 | / \
446 | / \
447 | / \
448 | / \
449 | / \
450 | / \
451 | / \
452 | / \
453 | / \
454 | / \
455 | / \
456 | / \
457 | / \
458 | / \
459 | / \
460 | / \
461 | / \
462 | / \
463 | 000X000 000X000
464 | / \ / \
465 | / \ / \
466 | / \ / \
467 | / \ / \
468 | / \ / \
469 | / \ / \
470 | / \ / \
471 | / \ / \
472 | / \ / \
473 | 000X000 000X000 000X000 000X000
474 | / \ / \ / \ / \
475 | / \ / \ / \ / \
476 | / \ / \ / \ / \
477 | / \ / \ / \ / \
478 | 000X000 000X000 000X000 000X000 000X000 000X000 000X000 000X000
479 |
480 | ```
481 |
482 | ## IV. Hybrid Algorithm
483 |
484 | - Set spaces' length to **3 chars** or **4 chars** depending on node length value is even or odd.
485 | - Set nodes' length to the maximum node value's length and type (odd/even).
486 |
487 | | Advantages | Disadvantages |
488 | | :-- | :-- |
489 | | Nodes' and spaces' lengths can be both even and odd in the same tree | |
490 | | Branching & spacing depends on whether the node length value is even or odd | |
491 |
492 | ### Hybrid Trees
493 |
494 | ```shell
495 |
496 | +----------------------------------------------+-----------------------------------------------+
497 | | 2-char-length-node + 4-char-length-space | 3-char-length-node + 3-char-length-space |
498 | +----------------------------------------------+-----------------------------------------------+
499 | | XX | 0X0 |
500 | | /\ | / \ |
501 | | / \ | / \ |
502 | | / \ | / \ |
503 | | / \ | / \ |
504 | | / \ | / \ |
505 | | / \ | / \ |
506 | | / \ | / \ |
507 | | / \ | / \ |
508 | | / \ | / \ |
509 | | / \ | / \ |
510 | | / \ | / \ |
511 | | XX XX | 0X0 0X0 |
512 | | /\ /\ | / \ / \ |
513 | | / \ / \ | / \ / \ |
514 | | / \ / \ | / \ / \ |
515 | | / \ / \ | / \ / \ |
516 | | / \ / \ | / \ / \ |
517 | | XX XX XX XX | 0X0 0X0 0X0 0X0 |
518 | | /\ /\ /\ /\ | / \ / \ / \ / \ |
519 | | / \ / \ / \ / \ | / \ / \ / \ / \ |
520 | | XX XX XX XX XX XX XX XX | 0X0 0X0 0X0 0X0 0X0 0X0 0X0 0X0 |
521 | +----------------------------------------------+-----------------------------------------------+
522 |
523 | +----------------------------------------------+-----------------------------------------------+
524 | | Hybrid-even-root | Hybrid-odd-root |
525 | +----------------------------------------------+-----------------------------------------------+
526 | | XX | 0X0 |
527 | | /\ | / \ |
528 | | / \ | / \ |
529 | | / \ | / \ |
530 | | / \ | / \ |
531 | | / \ | / \ |
532 | | / \ | / \ |
533 | | / \ | / \ |
534 | | / \ | / \ |
535 | | / \ | / \ |
536 | | / \ | / \ |
537 | | / \ | / \ |
538 | | XX 0X0 | XX 0X0 |
539 | | /\ / \ | /\ / \ |
540 | | / \ / \ | / \ / \ |
541 | | / \ / \ | / \ / \ |
542 | | / \ / \ | / \ / \ |
543 | | / \ / \ | / \ / \ |
544 | | XX 0X0 XX 0X0 | XX 0X0 XX 0X0 |
545 | | /\ / \ /\ / \ | /\ / \ /\ / \ |
546 | | / \ / \ / \ / \ | / \ / \ / \ / \ |
547 | | XX 0X0 XX 0X0 XX 0X0 XX 0X0 | XX 0X0 XX 0X0 XX 0X0 XX 0X0 |
548 | +----------------------------------------------+-----------------------------------------------+
549 |
550 | ```
551 |
--------------------------------------------------------------------------------