-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbinary-search-tree
More file actions
329 lines (288 loc) · 10.6 KB
/
binary-search-tree
File metadata and controls
329 lines (288 loc) · 10.6 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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#include "binary-search-tree.h"
#include "iostream"
#include "queue"
using namespace std;
BinarySearchTree::Node::Node(DataType newval)
{
val = newval; //set value of node to new value
left = nullptr; //left child node pointer to null
right = nullptr; //right child node pointer to null
}
// Optional function that recursively gets the maximum depth for a given node.
int BinarySearchTree::getNodeDepth(Node* n) const
{
if (n == nullptr){
return -1;
}
else if (n->left == nullptr && n->right == nullptr){
return 0; //only root node present -> height = 0
}
else {
int leftdepth = getNodeDepth(n->left); //height if you go down left nodes only
int rightdepth = getNodeDepth(n->right);//height if you go down right nodes only
if (leftdepth > rightdepth){//if left depth is max depth
return 1 + leftdepth;//left depth is height from the left node so add 1 for the parent
}
else {//if right depth is max
return 1 + rightdepth;
}
//return 1 + max(getNodeDepth(n->left), getNodeDepth(n->right));
}
}
// Default constructor to initialize the root.
BinarySearchTree::BinarySearchTree()
{
root_ = nullptr; //initialize a null root node
size_ = 0; //set size to 0
}
// Destructor of the class BinarySearchTree. It deallocates the memory
// space allocated for the binary search tree.
BinarySearchTree::~BinarySearchTree()
{
//similar to level traversal print function but instead of printing each node, delete it
if (root_ == nullptr){
return; //if empty tree don't do anything
}
queue <Node*> q; //make an empty queue
q.push(root_); //insert root node to the back of the queue
while (q.empty() == false){//while there is something in the queue
Node *p = q.front();//points to the node at the front of the queue
if (p->left != nullptr){//if left child node is not empty, add it to the back of queue
q.push(p->left);
}
if (p->right != nullptr){//if right child node is not empty, add it to the back of queue
q.push(p->right);
}
delete p; //delete current node
p = NULL;
q.pop();//remove first element in list (current node)
}
}
// Returns the number of nodes in the tree.
unsigned int BinarySearchTree::size() const
{
return size_;
}
// Returns the maximum value of a node in the tree. You can assume that
// this function will never be called on an empty tree.
BinarySearchTree::DataType BinarySearchTree::max() const
{
Node* temp = root_; //temp pointer to root
while (temp->right != nullptr){
temp = temp->right;//traverse through right nodes
}
int maxval = temp->val;//max value is the very last right node
return maxval;
}
// Returns the minimum value of a node in the tree. You can assume that
// this function will never be called on an empty tree.
BinarySearchTree::DataType BinarySearchTree::min() const
{
Node* temp = root_; //temp pointer to root
while (temp->left != nullptr){
temp = temp->left;//traverse through left nodes
}
int minval = temp->val;//min value is the very last left node
return minval;
}
// Returns the maximum depth of the tree. A tree with only the root node has a
// depth of 0. You can assume that this function will never be called on an
// empty tree.
unsigned int BinarySearchTree::depth() const
{
return getNodeDepth(root_);
}
//done in level-order traversal (BFT)
// You can print the tree in whatever order you prefer. However, methods such
// as in-order or level-order traversal could be the most useful for debugging.
void BinarySearchTree::print() const
{
if(root_ == nullptr){
cout << "tree is empty, nothing to print" << endl;
return;
}
queue <Node*> q; //make an empty queue
q.push(root_); //insert root node to the back of the queue
while (q.empty() == false){//while there is something in the queue
Node *p = q.front();//points to the node at the front of the queue
q.pop();//remove first element of queue
cout << p->val << " -> ";
if (p->left != nullptr){//if left child node is not empty, add it to the back of queue
q.push(p->left);
}
if (p->right != nullptr){//if right child node is not empty, add it to the back of queue
q.push(p->right);
}
cout << endl;
}
}
// Returns true if a node with the value val exists in the tree; otherwise,
// it returns false. (basically a search function)
bool BinarySearchTree::exists(DataType val) const
{
Node* currentnode = root_;
while (currentnode != nullptr){
if (currentnode->val == val){ //if current node val matches given value return true
return true;
}
else if(val > currentnode->val){//if val is greater than parent node search right
currentnode = currentnode->right;
}
else{//if val is less than parent node value search left
currentnode = currentnode->left;
}
}
return false; //if val does not exist in tree return false
}
// Returns a pointer to the root node
BinarySearchTree::Node* BinarySearchTree::getRootNode()
{
return root_;
}
// Returns the root node pointer address
BinarySearchTree::Node** BinarySearchTree::getRootNodeAddress()
{
//Node **addressofroot = &root_;
return &root_;
}
// Inserts the value val into the tree. Returns false if val already exists in
// the tree, and true otherwise.
bool BinarySearchTree::insert(DataType val)
{
if (exists(val)){ //if value already exists in tree return false
return false;
}
else if (size_ == 0){//if tree is empty
root_ = new Node(val);//create new root node with val
size_ = size_ + 1;//update tree size
return true;
}
else{//tree is not empty and value is not already there -> insert node
Node *current = root_;
Node *parent = nullptr;
while (current != nullptr){//set current to the place where node is inserted, current is child of parent
parent = current;
if (val < current->val){
current = current->left;
}
else{
current = current->right;
}
}
if (val < parent->val){//if val is less than parent val then insert left child
parent->left = new Node(val);
size_ = size_ + 1;//update tree size
return true;
}
else{
parent->right = new Node(val);
size_ = size_ + 1;//update tree size
return true;
}
}
}
// Removes the node with the value val from the tree. Returns true if successful,
// and false otherwise.
bool BinarySearchTree::remove(DataType val)
{
if (!exists(val)){//if val does not exist in tree (or empty tree), nothing to remove
return false;
}
//find the node to remove
Node *current = root_;
Node *parent = NULL;
bool found = false;
while (current != nullptr){
if (current->val == val){//if val is the root val
found = true;
break;
}
else if (val < current->val){ //if val is less than root, move to left subtree
parent = current;
current = current->left;
}
else { //if val is greater than root, move to right subtree
parent = current;
current = current->right;
}
}
//now current = the node to remove, parent is the parent node of current
//if leaf node, remove it, return true (no children)
if (current->right == nullptr && current->left == nullptr){//if node to remove is leaf node
if (current->val == root_->val){//if node to remove is root
root_ = nullptr;
}
else if (parent->left == current){ //if the left child of parent is node to remove
parent->left = nullptr;//remove left child
}
else {
parent->right = nullptr;//else remove right child
}
delete current;
current = nullptr;
size_ = size_ - 1; //update size of tree
return true;
}
//if only one child node, remove val, link val's parent with val's only child
else if (current->right == nullptr && current->left != nullptr){//only child is left node
if (parent->left->val == current->val){
parent->left = current->left; //link parents left with the only child (replace current node)
}
else {
parent->right = current->left;//link parents right with the only child (replace current node)
}
delete current;
current = nullptr;
size_ = size_ - 1; //update size of tree
return true;
}
else if (current->right != nullptr && current->left == nullptr){//only child is right node
if (parent->left == current){
parent->left = current->right;
}
else {
parent->right = current->right;
}
delete current;
current = nullptr;
size_ = size_ - 1; //update size of tree
return true;
}
//if val has two child nodes, replace val node value with predecessor or successor value, delete original predecessor or successor
else if (current->right != nullptr && current->left != nullptr){ //2 children
//find predecessor (max value in left subtree)
Node* predecessor = current->left;
Node* predecessorParent = current;
while (predecessor->right != nullptr){ //find the right most in left subtree (largest val, could be leaf node or have one left child)
predecessorParent = predecessor;
predecessor = predecessor->right;
}
current->val = predecessor->val; //replace val of node to remove with predecssor
//now need to delete predecessor
//special case
if (predecessorParent == current){
current->left = predecessor->left; //connect left child of predecessor with current
}
//normal case
else{
if (predecessor->left == nullptr){ //if predecessor has no child
predecessorParent->right = nullptr; //remove predecessor
}
else { //if it has left child
predecessorParent->right = predecessor->left; //connect with parent
}
}
delete predecessor;
predecessor = nullptr;
size_ = size_ - 1; //update size of tree
return true;
}
}
void BinarySearchTree::updateNodeBalance(Node *n) {
if (n == NULL){
n->avlBalance = 0;
}
else{
n->avlBalance = getNodeDepth(n->left) - getNodeDepth(n->right);
}
}