forked from 2unaa/Data-Structures-and-Algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBST.h
More file actions
557 lines (476 loc) · 15 KB
/
BST.h
File metadata and controls
557 lines (476 loc) · 15 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
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
/****************
Template created by Kazumi Slott
CS311
Your name: ???????
Your programmer number: ?????
Hours spent?: ???
Any difficulties?: ??????
*****************/
#ifndef BST_H
#define BST_H
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
//forward declaration of BST class. We need this because BST class is used as a friend in Node.
//Check your stack_L_T.h if you don't know what to put here.
//?????
//?????
template <class T> //forward declaration needed so we can make stack class a friend of node
class BST;
template <class T> //forward declaration needed so we can make operator<< a friend of node and Stack
ostream& operator<<(ostream& o, const BST<T>& s);
//Make Node and BST template classes.
//You put the class definition and member function implementations in .h when you use template.
//If you don't know how to make them template,
//Check page 3 of CS211 "Lec Notes on Exception Handling". I have a template stack class there.
//Also you made stack_L_T.h using template at the beginning of this semester.
template <class T> //make it a templare class
class Node
{
friend class BST<T>; //BST wants to access private members of Node
private:
T el;
Node* right;
Node* left;
public:
Node() {right = left = NULL;}; //default constructor. set right and left to NULL
Node(const T& e){el = e; right = NULL; left = NULL;};
T getEl() const {return el;} //returns el
};
template <class T>//Make it a template class
class BST
{
private:
Node<T>* root; //check stack_L_T.h to see how to declare top
//You will need 10 private functions here. WHY private?
void insertNodeR(Node<T>*& p, const T& e);
void inOrderPrint(Node<T>* p);
void preOrderPrint(Node<T>* p);
void postOrderPrint(Node<T>* p);
int getMaxLength(Node<T>* p);
int getMinLength(Node<T>* p);
int getNumNodes(Node<T>* p);
Node<T>* searchR(Node<T>* p, const T& e);
int getEvenNodes(Node<T>* p);
void destroy(Node<T>* p);
void remove(Node<T>*& p);
public:
BST() {root = NULL;} //implement constructor here
~BST();
void insertNodeR(const T& e);
void insertNodeI(const T& e);
void inOrderPrint();
void preOrderPrint();
void postOrderPrint();
int getMaxLength();
int getMinLength();
int getNumNodes();
int getEvenNodes();
Node<T>* searchI(const T& e);
Node<T>* searchR(const T& e);
bool remove(const T& e);
void DFTprint();
void BFTprint();
};
//implement the member functions in the header if you are making a template class
//destructor.
//If you don't know how to make the destructor, check the following
//CS211 Lec notes on BST recursive functions - destroy and in order traversal
//CS211 Lecture recording - Lecture 4/28(Wed) - BST:: inOrderPrint(), destroy()
template <class T>
BST<T>::~BST()
{
destroy(root);
}
template <class T>
void BST<T>::destroy(Node<T>* p) //private function. WHY?
{
if(p == NULL)
{
return;
}
destroy(p->left);
destroy(p->right);
delete p;
//destroy all nodes
}
//If you don't know how to make the insert function using recursion, check the following.
//CS211 Lecture Notes on BST – insertNode
//CS211 Lecture recording - Lecture 4/26(Mon) - DLL::deleteFront, BST::insert(), search()
template <class T>
void BST<T>::insertNodeR(const T& e)
{
insertNodeR(root, e);
}
template <class T>
void BST<T>::insertNodeR(Node<T>*& p, const T& e) //private function. WHY?
{
if(p == NULL)
{
p = new Node<T>(e);
}
else if(e < p->el)
{
insertNodeR(p->left, e);
}
else if(e >= p->el)
{
insertNodeR(p->right, e);
}
}
//This is an insert function using iteration.
//You will see insert function using iteration is unwieldy compared to that using recursion above.
//The hemework document "HMWK BST - reveiw of cs211" has a diagram to show how this function works.
template <class T>
void BST<T>::insertNodeI(const T& e)
{
Node<T>* newNode = new Node<T>(e);
Node<T>* p = root;
Node<T>* parent = NULL; //points to the parent of p.
//move p to NULL
while(p != NULL)
{
//parent points to the parent node while p points to the left or right child.
parent = p;
if(e < p->el)
p = p->left;
else //if(p->el <= e)
p = p->right;
}
if(parent == NULL) //tree is empty
root = newNode;
else if(e < parent->el) //insert a child as the parent's left child
parent->left = newNode;
else if(parent->el <= e) //insert a child as the parent's left child
parent->right = newNode;
}
//If you don't how to make this, check the following
//CS211 Lec notes on BST recursive functions - destroy and in order traversal
//CS211 Lecture recording - Lecture 4/28(Wed) - BST:: inOrderPrint(), destroy()
template <class T>
void BST<T>::inOrderPrint()
{
inOrderPrint(root);
}
template <class T> //private function. WHY?
void BST<T>::inOrderPrint(Node<T>* p)
{
if(p== NULL)
{
return;
}
inOrderPrint(p->left);
cout << p->el << "-->";
inOrderPrint(p->right);
}
template <class T>
void BST<T>::preOrderPrint()
{
preOrderPrint(root); //pre means print parent->left child ->right child
}
template <class T>
void BST<T>::preOrderPrint(Node<T>* p) //private function. WHY?
{
if(p == NULL)
{
return;
}
cout << p->el << "-->"; //print out
preOrderPrint(p->left); //left
preOrderPrint(p->right); //right
}
template <class T>
void BST<T>::postOrderPrint()
{
postOrderPrint(root); //post means left->right->parent last
}
template <class T>
void BST<T>::postOrderPrint(Node<T>* p) //private function. WHY?
{
if(p == NULL)
{
return;
}
postOrderPrint(p->left); //left of tree
postOrderPrint(p->right); //right of tree
cout << p->el << "-->";
}
//If you don't know how to make this, check the following
//Lec Notes on BST :: Recursive Functions – getNumNodes
//CS211 Lecture recording - Lecture 4/30(Fri) - BST::getNumNodes, phase 3 of college
template <class T>
int BST<T>::getNumNodes()
{
return getNumNodes(root);
}
template <class T>
int BST<T>::getNumNodes(Node<T>* p) //private function WHY?
{
if(p == NULL)
{
return 0;
}
else
{
return getNumNodes(p->left) + getNumNodes(p->right) + 1;
}
}
//This function return the maximum length from the root. If there is only one node, this function returns 1.
template <class T>
int BST<T>::getMaxLength()
{
return getMaxLength(root);
}
template <class T>
int BST<T>::getMaxLength(Node<T>* p) //private function. Why?
{
if(p == NULL)
{
return 0;
}
else
{
int left = getMaxLength(p->left) + 1; //get the value of the left sid \
int right = getMaxLength(p->right) + 1; //get the value of the right \
if(left >= right) //if left is greater than right
{
return left;
}
else //if right is greater than left
{
return right;
}
}
}
template <class T>
int BST<T>::getMinLength()
{
getMinLength(root);
}
template <class T>
int BST<T>::getMinLength(Node<T>* p) //private function. WHY?
{
if(p == NULL)
{
return 0;
}
else
{
int left, right;
left = getMinLength(p->left) + 1;//left side
right = getMinLength(p->right) + 1;//right side
if(left < right)//if left side is less than right
{
return left;//return left
}
if(right <= left)//if right side is less than left
{
return right;//return right
}
}
}
//This function will return the number of even elements
template <class T>
int BST<T>::getEvenNodes()
{
getEvenNodes(root);
}
template <class T>
int BST<T>::getEvenNodes(Node<T>* p) //private function. WHY?
{
int num = 0;
if(p == NULL)
{
return num;
}
else
{
if(p->el % 2 == 0)
{
num++;
}
return num + getEvenNodes(p->left) + getEvenNodes(p->right);
}
}
//Make a search function using iteration. Return the pointer to the node having e
//return NULL if e is not found.
template <class T>
Node<T>* BST<T>::searchI(const T& e)
{
Node<T>* p = root;
while(p != NULL)
{
if(p->el == e || p == NULL)
{
return p;
}
else if(p->el > e)
{
p = p->left;
}
else if(p-> el <= e)
{
p = p->right;
}
}
}
//Make a search function using recursion.
//Return the pointer to the node having e or return NULL if e is not found.
template <class T>
Node<T>* BST<T>::searchR(const T& e)
{
return searchR(root, e);
}
template <class T>
Node<T>* BST<T>::searchR(Node<T>* p, const T& e) //private function. WHY?
{
if(p == NULL)
{
return NULL; //if it is still not found after all the searching, return false
}
else if(p-> el == e) //if the element is found
{
return p;
}
else if(e > p-> el) //if the element is larger than the root
{
searchR(p->right, e); //search through the right side
}
else if(e < p-> el) //if the element is smaller than the root
{
searchR(p->left, e); //if it is still not found after, return fal\
}
}
template <class T>
void BST<T>::BFTprint() //Breadth First Traversal Print
{
//Use the library's queue. https://cplusplus.com/reference/queue/queue/
//Make sure to include <queue> at the top
queue<Node <T>*> q; //create a queue obj of POINTERS to Nodes
//algorithm is discussed in lecture
//NOTICE
//front() gives you the front element but it doesn't remove it from the qu\eue.
//pop() removes the front element
if(root == NULL)
{
return;
}
q.push(root);//push root in the queue
while(!q.empty()) //while its not empty
{
Node<T>* front = q.front();//gets the front
cout << front->el << "-->";
q.pop();
if(front->left != NULL)//if the left has pointers
{
q.push(front->left);//push to the left side
}
if(front->right != NULL)//if the right has pointers
{
q.push(front->right);//push to the right side
}
}
}
template <class T>
void BST<T>::DFTprint() //Depth First Traversal Print
{
//Use the library's stack class. https://cplusplus.com/reference/stack/sta\ck/
stack<Node <T>*> s; //Make sure to include <stack> at the top
//create a stack of POINTERS to Nodes
//top() will give you the top element but it will not remove it from the stack.
//pop() removes the top element.
if(root == NULL)
{
return;
}
s.push(root);
while(!s.empty())//if the stack is not empty
{
Node<T>* top = s.top();//set the top element to the top function
cout << top->el << "-->";//pop top and print
s.pop();
if(top->right != NULL)//if the top's right is not empty
{
s.push(top->right);//push right kid if any
}
if(top->left != NULL)
{
s.push(top->left);//push left kid if any
}
}
}
template <class T>
bool BST<T>::remove(const T& e) //public function
{
Node<T>* del = root; //del will point to the node to be deleted
Node<T>* parent = NULL; //parent will point to the parent of the node to be deleted
//look for e in the tree
while(del!=NULL && del->el != e) //If root is NULL, del is NULL to start with. While won't be entered and return false down below.
{
parent = del;//parent follows del. In other words, del is ahead of parent. --> you did something similar in insertI()
//del will eventually point to the node to be deleted.
if(del->el > e) //if the del is greater than e
{
del = del->left; //move del to the left
}
else //if del is less than or equal to e
{
del = del->right; //move del to the right
}
}
//e doesn't exist or tree is empty.
if(del == NULL)
{
return false;
}
//check to see if root should be removed
if(parent==NULL) //if the element is the root
remove(root); //root will change. call the other remove function down below
//We are deleting a node other than the root node. Figure out if del's node is left or right child of parent's node
else if(parent->left->el == e) //parent's left child to be removed
remove(parent->left);
else //parent's right child to be removed
remove(parent->right);
//deleted the node with e
return true;
}
template <class T>
//p comes out of the parent node and points to the node to be deleted OR points to root if root is the one to be deleted.
//p will point to the grandchild (child node of the node to be deleted) if the node to be deleted has only one child or will point to NULL if p is root
//the node to be deleted has no children. p will change. That is why we need to use &.
void BST<T>::remove(Node<T>*& p) //private function
{
Node<T>* temp = p; //temp points to the node to be deleted initially
Node<T>* t_parent; //t_parent will point to the parent node of temp's node
//the node to be deleted has no right child (Check Diagram1-Right and Left in the homework document "HMWK BST - BFT, DFT and remove" under "Assignment s")
//If the node to be deleted has no children, the following if will be executed.(Check Diagram2-Right and Left)
if(p->right == NULL) //if there is no right child
p = p->left; //p(The left or right coming out of parent of del's node) now points to the root of the left subtree under del's node. DONE. If the node to be deleted has no children, p is set to NULL because p->left is NULL.
//the node to be deleted has no left child (Check Diagram 3-Right and Left \
)
else if(p->left == NULL) //if there is no left child
p = p->right;//p(The left or right coming out of parent of del's node) now points to the root of the right subtree under del's node. DONE.
//If the node to be deleted has 2 children
else
{
//we are going to replace e by the largest value in the left subtree
temp = p->left; //temp points to the root of the left subtree under the node to be deleted to start with
t_parent = p; //t_parent points to the node to be deleted to start with
//go to the largest value in the left subtree under the node to be deleted by going all the way down to right
while(temp->right != NULL)
{
t_parent = temp; //temp is ahead of t_parent
temp = temp->right; //temp will eventually point to the largest value
}
//copy the largest value into the node to be deleted
p->el=temp->el;
if(temp == p->left) //the largest value is the direct left child of the node whose value was replaced by the largest (Diagram 4-one child or no children)
p->left = temp->left; //connect the left of the node whose value was replaced by the largest value to the left child of the node that has the largest value
else //the largest value is NOT the direct left child of the node whose value was replaced by the largest (Diagram 5-one child and no children)
t_parent->right=temp->left; //If the node with the largest value doesn't have any chil dren, t_parent->right is set to NULL.
}
//finally delete temp;
delete temp;
}
#endif