forked from BYUCS235/AVL-Lab
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNode.cpp
More file actions
190 lines (159 loc) · 4.57 KB
/
Node.cpp
File metadata and controls
190 lines (159 loc) · 4.57 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
#include "Node.h"
#include <iostream>
Node::~Node()
{
if(left_child != nullptr)
delete left_child;
if(right_child != nullptr)
delete right_child;
}
int Node::getHeight(const Node* _this_node)
{
return (_this_node != nullptr) ? _this_node->height : 0;
}
void Node::recalcHeight()
{
height = 1 + ((getHeight(left_child) > getHeight(right_child)) ? getHeight(left_child) : getHeight(right_child));
}
void Node::rebalance()
{
// Recalculate _local_root's height
// make sure that any nodes not being checked for rebalancing call this directly
recalcHeight();
// If the upper (right) half of this local tree is heavyier, rotate the tree to the left
if(getHeight(right_child)-1 > getHeight(left_child))
{
// If the right half of tree is skewed inward, rotate it out first to avoid repetitive rotation
if(getHeight(right_child->left_child) > getHeight(right_child->right_child))
right_child->rotateRight();
rotateLeft();
}
// If the lower (left) half of this local tree is heavyier, rotate the tree to the right
if(getHeight(left_child)-1 > getHeight(right_child))
{
// If the left half of tree is skewed inward, rotate it out first to avoid repetitive rotation
if(getHeight(left_child->right_child) > getHeight(left_child->left_child))
left_child->rotateLeft();
rotateRight();
}
}
void Node::rotateLeft()
{
int temp = data;
data = right_child->data;
right_child->data = temp;
// One of the new_root's nodes is going to get swapped around. Save it in the meantime.
Node* trade = right_child;
// Re-hook up the old root, new root, and center node
right_child = right_child->right_child;
trade->right_child = trade->left_child;
trade->left_child = left_child;
left_child = trade;
// Recalculate both the old and new roots' heights
left_child->recalcHeight();
recalcHeight();
}
void Node::rotateRight()
{
int temp = data;
data = left_child->data;
left_child->data = temp;
// One of the new_root's nodes is going to get swapped around. Save it in the meantime.
Node* trade = left_child;
// Re-hook up the old root, new root, and center node
left_child = left_child->left_child;
trade->left_child = trade->right_child;
trade->right_child = right_child;
right_child = trade;
// Recalculate both the old and new roots' heights
right_child->recalcHeight();
recalcHeight();
}
bool Node::add(const int &_data)
{
// End condition - duplicate value
if(_data == data)
return false;
Node*& next_node = (_data < data) ? left_child : right_child;
// End condition - value not found, adding
if(next_node == nullptr)
{
next_node = new Node(_data);
recalcHeight();
return true;
}
// Recursive return. Calls rebalance() if returning true
if(next_node->add(_data))
{
rebalance();
return true;
}
return false;
}
int Node::remove(const int &_data)
{
// End condition - value found, removing
if(data == _data)
{
if(height == 1)
{ // This deals with nodes that have no child nodes
Node* to_remove = this;
remove(to_remove);
return -1;
}
if((right_child != nullptr) && (left_child != nullptr))
{ // This deals with nodes that have two child nodes
replaceWithRightmostOf(left_child);
rebalance();
}
else
{ // This deals with nodes that have only one child node: just save, replace, and delete
Node* replacement = (left_child != nullptr) ? left_child : right_child;
*this = *replacement;
remove(replacement);
rebalance();
}
return 1;
}
Node*& next_node = (data > _data) ? left_child : right_child;
if(next_node == nullptr)
return 0;
// Recursion called with right or left child as determined by an inline conditional
switch(next_node->remove(_data))
{
case 0:
return 0;
case -1:
next_node = nullptr;
default:
rebalance();
return 1;
}
}
void Node::remove(Node*& _this_node)
{
if(_this_node->height == 1)
{
delete _this_node;
_this_node = nullptr;
return;
}
Node* replacement = (_this_node->right_child != nullptr) ? _this_node->right_child : _this_node->left_child;
*_this_node = *replacement;
replacement->right_child = nullptr;
replacement->left_child = nullptr;
delete replacement;
}
void Node::replaceWithRightmostOf(Node* &_to_remove)
{
// End condition - _to_remove holds the value immediately preceding this node
if(_to_remove->right_child == nullptr)
{
data = _to_remove->data;
remove(_to_remove);
return;
}
// Recursion
replaceWithRightmostOf(_to_remove->right_child);
_to_remove->rebalance();
}