avl trees ii

18
1 AVL Trees II Implementation

Upload: ciara-crosby

Post on 31-Dec-2015

20 views

Category:

Documents


0 download

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 Presentation

TRANSCRIPT

Page 1: AVL Trees II

1

AVL Trees II

Implementation

Page 2: AVL Trees II

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

Page 3: AVL Trees II

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

};

Page 4: AVL Trees II

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;

};

Page 5: AVL Trees II

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

Page 6: AVL Trees II

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);

}

}

Page 7: AVL Trees II

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);

}

}

...

Page 8: AVL Trees II

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

Page 9: AVL Trees II

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.

Page 10: AVL Trees II

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.

Page 11: AVL Trees II

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

Page 12: AVL Trees II

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

Page 13: AVL Trees II

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

Page 14: AVL Trees II

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.

Page 15: AVL Trees II

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

Page 16: AVL Trees II

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.

Page 17: AVL Trees II

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;

}

Page 18: AVL Trees II

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.