avl trees ii
DESCRIPTION
AVL Trees II. Implementation. Implementation. Download: http://www.cse.usf.edu/~turnerr/Data_Structures/Downloads/2011_03_28_AVL_Tree/ File AVL_Tree_Demo.zip Project contains: AVL_BST.h Our most recent BST template updated to implement an AVL tree. - PowerPoint PPT PresentationTRANSCRIPT
1
AVL Trees II
Implementation
2
Implementation
Download: http://www.cse.usf.edu/~turnerr/Data_Structures/Dow
nloads/2011_03_28_AVL_Tree/ File AVL_Tree_Demo.zip
Project contains: AVL_BST.h Our most recent BST template updated
to implement an AVL tree. main.cpp Uses the AVL BST to replicate the states
example from last class.
Extract, build, and run
3
Explore the Code
Enums used to specify direction of descent and kind of rotation needed
In AVL_BST.henum direction {dir_left, dir_right, dir_none};
enum rotation_type
{
rotate_type_left,
rotate_type_right,
rotate_type_left_right,
rotate_type_right_left
};
4
New Node Class
template<typename T>
class AvlNode
{
public:
AvlNode()
{
level = position = left = right = 0;
}
AvlNode(const T& el, AvlNode *l = 0, AvlNode *r = 0)
{
data = el; left = l; right = r;
level = position = 0;
}
T data;
int balance_factor;
int position;
int level;
AvlNode *left, *right;
};
5
Class AVL_BST
The insert method has been changed (radically) in order to implement AVL tree rebalancing.
Now a recursive method.
Public method declaration unchanged:void insert(const T&);
New internal method:void insert(const T& item, // Input
AvlNode<T>** incoming_ptr, // Input
bool& subtree_height_increased, // Output
direction& dir); // Output
6
Public Insert Method
// Public insert method
template <typename T>
void AVL_BST<T>::insert(const T& item)
{
// Return values from internal insert method. Not used here.
bool childs_subtree_height_increased;
direction childs_direction;
if (root == 0)
{
// Inserting into an empty tree.
root = new AvlNode<T>(item);
}
else
{
insert(item, &root,
childs_subtree_height_increased,
childs_direction);
}
}
7
Internal insert method
// Internal (protected) insert method
template <typename T>
void AVL_BST<T>::insert(const T& item, // Input
AvlNode<T>** incoming_ptr, // Input
bool& subtree_height_increased, // Output
direction& dir) // Output
{
AvlNode<T>* node = *incoming_ptr; // Current node
if (item < node->data)
{
dir = dir_left;
if (node->left == 0)
{
insert_left(item, incoming_ptr, subtree_height_increased, dir);
}
else
{
descend_left(item, incoming_ptr, subtree_height_increased, dir);
}
}
...
8
Internal insert method (continued)
else if (node->data < item)
{
dir = dir_right;
if (node->right == 0)
{
insert_right(item, incoming_ptr, subtree_height_increased, dir);
}
else
{
descend_right(item, incoming_ptr, subtree_height_increased, dir);
}
}
else // Item found. (Shouldn't happen)
{
throw "Attempt to add an item already in the tree";
}
}
Symmetrical to > case
9
insert_right
template <typename T>
void AVL_BST<T>::insert_right(const T & item, // Input
AvlNode<T>** incoming_ptr, // Input
bool& subtree_height_increased, // Output
direction& dir) // Output
{
AvlNode<T>* node = *incoming_ptr; // Current node
cout << endl << "Inserting " << item << " at " << node->data
<< " as right child" << endl;
assert(node->right == 0);
node->right = new AvlNode<T>(item);
...
Insert new node into tree.
10
insert_right (continued)
dir = dir_right;
if (node->left == 0)
{
// This node was previously a leaf.
subtree_height_increased = true;
node->balance_factor = -1;
}
else
{
// Already had a left child, so no increase.
subtree_height_increased = false;
node->balance_factor = 0;
}
}
Report back to caller.
11
descend_right
template <typename T>
void AVL_BST<T>::descend_right(const T& item, // Input
AvlNode<T>** incoming_ptr, // Input
bool& subtree_height_increased, // Output
direction& dir) // Output
{
bool childs_subtree_height_increased; // Set by call to insert
direction childs_direction; // Set by call to insert
AvlNode<T>*node = *incoming_ptr; // Current node
assert(node->right != 0);
insert(item, &(node->right),
childs_subtree_height_increased,
childs_direction);
dir = dir_right;
if (!childs_subtree_height_increased)
{
subtree_height_increased = false;
return;
}
Recursive call
Report back to caller
12
descend_right (continued)
// Child's subtree height increased due to inserting the new node.
--node->balance_factor;
if (node->balance_factor < -1)
{
cout << endl << node->data << " requires rebalance" << endl;
display_v(cout, 4);
if (childs_direction == dir_right)
{
rotate_left(incoming_ptr);
}
else
{
rotate_right_left(incoming_ptr);
}
cout << endl << "After rotation: " << endl << endl;
display_v(cout, 4);
// After rotation, subtree height has not increased
subtree_height_increased = false;
return;
}
Report back to caller
13
descend_right (continued)
// No rotation at this level.
if (node->balance_factor == -1)
{
subtree_height_increased = true;
}
else
{
subtree_height_increased = false;
}
}
Report back to caller
14
rotate_right
template <typename T>
void AVL_BST<T>::rotate_right(AvlNode<T>** parent_link)
{
AvlNode<T>* node = *parent_link;
cout << endl << node->data << " rotate_right " << endl;
assert(node->left != 0);
AvlNode<T>* temp = node->left->right;
AvlNode<T>* pivot = node->left;
pivot->right = *parent_link;
*parent_link = pivot;
node->left = temp;
update_balance_factor(pivot);
update_balance_factor(node);
}
"pivot" is the left child of the node being rotated to the right.
It will take the place of the node being rotated, and the node being rotated will become its right child.
If it previously had a right child, that node will become the new left child of the node being rotated.
15
update_balance_factor
template <typename T>
void AVL_BST<T>::update_balance_factor(AvlNode<T>* node)
{
if (node->right == 0)
{
if (node->left == 0)
{
node->balance_factor = 0;
}
else
{
node->balance_factor = 1;
}
}
else
...
Update the balance factor of a node that has just been rotated.
There are only three possible values
16
update_balance_factor
else
{
if (node->left == 0)
{
node->balance_factor = -1;
}
else
{
int l = height(node->left);
int r = height(node->right);
assert (abs(l-r) < 2);
node->balance_factor = l - r;
}
}
}
node has a right child.
node has a right child and a left child.
17
Compute height of a subtree
template <typename T>
int AVL_BST<T>::height(AvlNode<T>* node)
{
int left_child_height = node->left ? height(node->left) : 0;
int right_child_height = node->right ? height(node->right) : 0;
return max(left_child_height, right_child_height) + 1;
}
18
Assignment
Study the AVL_BST code carefully. Try it with your own test cases.
Try to find errors. Major bragging rights to a student who
reports a significant bug. Be prepared to answer questions
about it.