-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathBinaryTree.js
More file actions
256 lines (234 loc) · 8.88 KB
/
BinaryTree.js
File metadata and controls
256 lines (234 loc) · 8.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
// Tree Data Structure: is usually visualized with the root node at the top; you can think of it as a natural tree flipped upside down.
// The root node is the top of the tree. Data points in the tree are called nodes. Nodes with branches leading to other nodes are referred to as the parent of the node the branch leads to (the child). A subtree refers to all the descendants of a particular node, branches may be referred to as edges, and leaf nodes are nodes at the end of the tree that have no children. Finally, note that trees are inherently recursive data structures. That is, any children of a node are parents of their own subtree, and so on. The recursive nature of trees is important to understand when designing algorithms for common tree operations. Look at this picture to understand this: https://2.bp.blogspot.com/-CApCcTOe1A0/TwppaUWiQsI/AAAAAAAABX4/sJv92_ZJzhE/s1600/Tree+Term.gif
// The tree data structure can have any number of branches at a single node, a binary tree can only have two branches for every node.
// A binary search tree adds these two characteristics:
// 1) Each node has up to two children
// 2) For each node, its left (subtree/descendants) is less than the current node, which is less than the right (subtree/descendants).
var displayTree = tree => console.log(JSON.stringify(tree, null, 2));
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
function BinarySearchTree() {
this.root = null;
this.findMin = function() {
if (this.root === null) return null;
let currentNode = this.root;
while (currentNode.left) {
currentNode = currentNode.left;
}
return currentNode.value;
};
this.findMax = function() {
if (this.root === null) return null;
let currentNode = this.root;
while (currentNode.right) {
currentNode = currentNode.right;
}
return currentNode.value;
};
this.add = function(e) {
let node = new Node(e);
if (this.root == null) {
this.root = node;
return;
} else {
this.search = function(item) {
if (e < item.value) {
if (item.left === null) {
item.left = node;
return;
} else {
this.search(item.left);
}
} else if (e > item.value) {
if (item.right == null) {
item.right = node;
return;
} else {
this.search(item.right);
}
} else {
return null;
}
};
this.search(this.root);
}
};
this.isPresent = function(value) {
if (this.root == null) {
return false;
} else {
let currentNode = this.root;
while (currentNode) {
if (value < currentNode.value) {
currentNode = currentNode.left;
} else if (value > currentNode.value) {
currentNode = currentNode.right;
} else {
return true;
}
}
return false;
}
};
this.isBalanced = function() {
return this.findMinHeight() + 1 >= this.findMaxHeight();
};
this.findMinHeight = function(node = this.root) {
if (node === null) {
return -1;
}
let leftHeight = this.findMinHeight(node.left);
let rightHeight = this.findMinHeight(node.right);
return Math.min(leftHeight, rightHeight) + 1;
// we are finding the height of a left subtree and a height of right subtree, then we getting the min value out of those two, then adding 1 to it, so that way it will add the min height of subtree (left or right, which ever is less) + root distance which is 1 which would mean the height of a tree
// https://www.youtube.com/watch?v=_pnqMz5nrRs&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=31
// https://www.youtube.com/watch?v=_SiwrPXG9-g
};
this.findMaxHeight = function(node = this.root) {
if (node === null) {
return -1;
}
let leftHeight = this.findMaxHeight(node.left);
let rightHeight = this.findMaxHeight(node.right);
return Math.max(leftHeight, rightHeight) + 1;
// we are finding the height of a left subtree and a height of right subtree, then we getting the min value out of those two, then adding 1 to it, so that way it will add the max height of subtree (left or right, which ever is more) + root distance which is 1 which would mean the height of a tree
// https://www.youtube.com/watch?v=_pnqMz5nrRs&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=31
// https://www.youtube.com/watch?v=_SiwrPXG9-g
};
/*
Depth First Search (3 ways to do DFS):
1) in-order: Get values in order from smallest to largest
2) pre-order: Get the roots/parents value first then their children. Note that last leaf nodes also have null childern, so in other words they are root/parent of their own childern as well.
3) post-order: Get the values of leafNodes/childern first, then their parents and so on. In other words the value of the tree's main root which is "this.root" would be in the end.
*/
this.inOrder = function() {
if (this.root === null) {
return null;
} else {
let result = [];
this.inOrderFunction = function(node) {
node.left && this.inOrderFunction(node.left);
result.push(node.value);
node.right && this.inOrderFunction(node.right);
};
this.inOrderFunction(this.root);
return result;
}
};
this.preOrder = function() {
if (this.root === null) {
return null;
} else {
let result = [];
this.preOrderFunction = function(node) {
result.push(node.value);
node.left && this.preOrderFunction(node.left);
node.right && this.preOrderFunction(node.right);
};
this.preOrderFunction(this.root);
return result;
}
};
this.postOrder = function() {
if (this.root === null) {
return null;
} else {
let result = [];
this.postOrderFunction = function(node) {
node.left && this.postOrderFunction(node.left);
node.right && this.postOrderFunction(node.right);
result.push(node.value);
};
this.postOrderFunction(this.root);
return result;
}
};
// this.levelOrder = function() {
// let results = [];
// let count = -1;
// if (this.root == null) {
// return null;
// } else {
// this.levelOrderFunction = function(node) {
// count += 1;
// results.push([count, node.value]);
// node.left && this.levelOrderFunction(node.left)
// node.right && this.levelOrderFunction(node.right)
// count -= 1;
// }
// this.levelOrderFunction(this.root)
// results = results.sort((a,b) => a[0]-b[0]);
// for (let i = 0; i < results.length; i++) {
// results[i] = results[i][1]
// }
// return results
// }
// }
// Breadth First Search: Getting all the nodes' values of the same level then next level ones, and so on. Which means the first level value would only be "one node's value" which would be the "this.root"
this.levelOrder = function() {
if (this.root == null) {
return null;
} else {
let Q = [this.root];
let results = [];
while (Q.length > 0) {
let node = Q.shift();
results.push(node.value);
node.left && Q.push(node.left);
node.right && Q.push(node.right);
}
return results;
}
};
this.reverseLevelOrder = function() {
if (this.root == null) {
return null;
} else {
let Q = [this.root];
let results = [];
while (Q.length > 0) {
let node = Q.shift();
results.push(node.value);
node.right && Q.push(node.right);
node.left && Q.push(node.left);
}
return results;
}
};
// Find the sum of the nodes of each level, using Depth First Search.
this.levelOrderSum = function() {
if (this.root == null) {
return null;
} else {
let count = -1;
let results = [];
this.search = function(node) {
count += 1;
results.push([count, node.value]);
node.left && this.search(node.left);
node.right && this.search(node.right);
count -= 1;
};
this.search(this.root);
results = results.sort((a, b) => a[0] - b[0]);
for (let i = 0; i < results.length - 1; i++) {
if (results[i][0] == results[i + 1][0]) {
let sum = results[i][1] + results[i + 1][1];
results[i][1] = sum;
results.splice(i + 1, 1);
i--;
}
}
return results;
}
};
}
let bst = new BinarySearchTree();
bst.add(100);
bst.add(50); bst.add(150);
bst.add(20); bst.add(80); bst.add(120); bst.add(180);
bst.add(10); bst.add(22); bst.add(75); bst.add(85); bst.add(115); bst.add(125); bst.add(175); bst.add(185);
// To View The Tree Diagram: https://drive.google.com/file/d/0B0S_683ssSvGdEpmdVAyS2Q1Z28/view?usp=sharing