-
Notifications
You must be signed in to change notification settings - Fork 0
/
avl.cc
269 lines (242 loc) · 5.99 KB
/
avl.cc
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
/*
Josue Montenegro
PA2: Implementation of AVL Tree
CS130A
*/
#include <iostream>
#include <sstream>
#include "avl.h"
#include <string>
using namespace std;
/*------------------------------
Public Methods
------------------------------*/
//inserts key 'e' into the tree and balances it
void AVLTree::Insert(const int32_t e)
{
return Insert(e, root, root);
}
//returns true if element can be accessed
bool AVLTree::Access(const int32_t e)
{
return Access(e, root);
}
//deletes key 'e' into the tree and balances it
void AVLTree::Delete(const int32_t e)
{
return Delete(e, root);
}
//PreOrder traversal of the tree
string AVLTree::PrintPreOrder() const {
result = "";
PrintPreOrder(root);
result.pop_back(); // gets rid of the the extra space at the end
return result;
}
//InOrder traversal of the tree
string AVLTree::PrintInOrder() const{
result = "";
PrintInOrder(root);
result.pop_back(); // gets rid of the the extra space at the end
return result;
}
/*------------------------------
Private Methods
------------------------------*/
/*
returns height of the current node
*/
int AVLTree::height (AVLNode * n){
if (n){
return n-> height;
}else{
return 0; // if node is poiting to NULL
}
}
/*
determines the balance factor of a node by looking at
at the height of its children
*/
int AVLTree::balFactor(AVLNode* n){
return height(n->right) - height(n->left);
}
/*
takes the greatest height from children and adds 1,
it becomes current node height
*/
void AVLTree::assignHeight(AVLNode * n){
int l = height(n->left);
int r = height(n->right);
n->height = (l>r ? l : r ) +1;
}
/*
prints root -> left child -> right child
*/
void AVLTree::PrintPreOrder(AVLNode * root) const{
if(root != NULL){
result += to_string(root->elem) + " ";
PrintPreOrder(root->left);
PrintPreOrder(root->right);
}
}
/*
prints left child -> root -> right child
*/
void AVLTree::PrintInOrder(AVLNode * root) const{
if(root != NULL){
PrintInOrder(root->left);
result += to_string(root->elem) + " ";
PrintInOrder(root->right);
}
}
/*
finds element with min key on a tree
it will be used to find the successor of a node
*/
AVLNode * AVLTree::findMin(AVLNode *t)
{
if(t != NULL)
while(t->left != NULL)
t = t->left;
return t;
}
/*
helper function to destroy the tree,
recursively deletes parent and then children
*/
void AVLTree::makeEmpty(AVLNode * & t)
{
if(t != NULL) {
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
t = NULL;
}
/*
Performs typical BST insertion operation and balances the tree
while the recursive calls get called of the stack
*/
void AVLTree::Insert(const int32_t e, AVLNode * & t, AVLNode * parent)
{
//in each call we need to remember the parent to perform balanceTree
if(root == NULL) {
root = new AVLNode(e, NULL);
return;
}
else{
if(t == NULL) {
t = new AVLNode(e,parent);
return;
}
//checks if insertion takes place in left or right subtree
else if(e < t->elem){
parent = t;
Insert(e, t->left,parent);
}
else if(e > t->elem){
parent = t;
Insert(e, t->right,parent);
}
//when the function recursively goes up
//it fixes the height and assigns proper rotations
t = balanceTree(parent); //makes sure subtree root updates
}
}
/*
it fixes the height of the tree with root p
and performs proper rotations
*/
AVLNode * AVLTree::balanceTree(AVLNode * p){
assignHeight(p);
if(balFactor(p)==-2) // p is left heavy
{
if(balFactor(p->left) > 0) //balFactor > 0 = double rotation case Left Right Left
p->left = rotateLeft(p->left); //left child points to result of its left rotation
return rotateRight(p);
}
if(balFactor(p)==2) // p is right heavy
{
if(balFactor(p->right) < 0) //balFactor < 0 = double rotation case Right Left Right
p->right = rotateRight(p->right); //right child points to result of its right rotation
return rotateLeft(p);
}
return p; //tree didn't need to be balanced yet, height was updated
}
/*
if n is left heavy we will rotateRight
*/
AVLNode* AVLTree::rotateRight(AVLNode * n){
//n represents y, parent of x
AVLNode * x = n->left;
//we switch pointers in the right order to get right shape
n->left = x->right;
x->right = n;
//we fixheight of n first since it is lower in the tree now
assignHeight(n);
assignHeight(x);
return x;
}
/*
symmetric function of rotateRight
*/
AVLNode * AVLTree::rotateLeft(AVLNode * x){
AVLNode * n = x->right;
x->right = n->left;
n->left = x;
//we fixheight of x first since it is lower in the tree now
assignHeight(x);
assignHeight(n);
return n;
}
/*
returns true if element 'e' could be found in the tree
*/
bool AVLTree::Access(const int32_t e, AVLNode * & t)
{
if(t == NULL)
return false;
else if(e == t->elem)
return true;
else if(e < t->elem)
return Access(e, t->left);
else
return Access(e, t->right);
}
/*
deletes key 'e' on the tree, replaces it with successor
and balances the tree if needed
*/
void AVLTree::Delete(const int32_t e, AVLNode * & t)
{
if(t == NULL) {
return;
}
//checks if deletion takes place in left or right subtree
else if(e < t->elem) {
Delete(e, t->left);
t = balanceTree(t); //balances the tree wit current root 't'
}
else if(e > t->elem) {
Delete(e, t->right);
t = balanceTree(t); //balances the tree wit current root 't'
}
//key 'e' matches t->element so we check if 't'
//has right and left children in oder to find
//successor node
else {
if(t->left != NULL && t->right != NULL) {
t->elem = findMin(t->right)->elem;
Delete(t->elem, t->right);
t = balanceTree(t); //balances the tree wit current root 't'
}
else {
//node to be deleted has either left or right subtree
//we can substitute deleted node with its left or right child
AVLNode *oldNode = t;
t = (t->left != NULL) ? t->left : t->right;
delete oldNode;
return;
}
}
}