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
|
#include <new>
#include "AVL.h"
#include <iostream>
/*
template <typename T> avl_tree <T> *insert ( avl_tree <T>*, const T& );
template <typename T> avl_tree <T> *create ( const T& );
template <typename T> avl_tree <T> *rotate ( avl_tree <T>*, int );
template <typename T> avl_tree <T> *rotate_double ( avl_tree <T>*, int );
template <typename T> avl_tree <T> *BalanceNeeded ( avl_tree <T>*, int, int );
template <typename T> avl_tree <T> *remove ( avl_tree <T>*, const T& );
*/
namespace AVL_TREE {
/***********MACROS**************/
#define None 0L
#define height(R) ((R) == None ? -1 : (R)->balance)
#define avl_max(a,b) (a > b ? a : b)
/*********MACROS*END************/
/**********FUNCTIONS************/
template <typename T>
avl_tree <T> *rotate ( avl_tree <T> *root, int dir ) {
/*Rotation here*/
avl_tree <T> *tmp(root->Link[!dir]);
root->Link[!dir] = tmp->Link[dir];
tmp->Link[dir] = root;
/*Calculate new length*/
int rll(height(root->Link[0])), rrl(height(root->Link[1]));
root->balance = 1 + avl_max(rll, rrl);
/*Update Balance factor*/
int lll(height(tmp->Link[!dir])), lrl(root->balance);
tmp->balance = 1 + avl_max(lll, lrl);
return tmp;
}
template <typename T>
avl_tree <T> *rotate_double ( avl_tree <T> *root, int dir ) {
root->Link[!dir] = rotate( root->Link[!dir], !dir);
return rotate (root, dir);
}
//Creates and returns a new tree with info
template <typename T>
avl_tree <T> *create ( const T& info ) {
avl_tree <T> *Tree = new (std::nothrow) avl_tree <T>;
if ( Tree ) {
Tree->data = info;
Tree->Link[0] = Tree->Link[1] = None;
}
return Tree;
}
//Called after every insertion to determine if tree needs rotation
template <typename T>
avl_tree <T> *BalanceNeeded ( avl_tree <T> *root, int dir, int bal ) {
if ( bal > 1 || bal < -1 ) {
//Only rotate if one side has length of 2 more than other side
avl_tree <T> *a(root->Link[dir]->Link[dir]), *b(root->Link[dir]->Link[!dir]);
if ( height(a) >= height(b) ) root = rotate(root, !dir);
else root = rotate_double (root, !dir);//zig-zag is a pain!
//!dir means to rotate in the opposite direction tree is growing
}
return root;
}
//Insert function
template <typename T>
avl_tree <T> *insert ( avl_tree <T>* root, const T& info ) {
int w, lh, rh;
switch ( root == None ) {
case 1:
root = create(info);
root->balance = 0;
break;
case 0:
w = (root->data <= info); //True means we go right otherwise left
root->Link[w] = insert( root->Link[w], info );
lh = height( root->Link[w] ); //Update left height
rh = height( root->Link[!w] );//Update right height
root->balance = 1 + avl_max( rh, lh ); //Set new height to max of left and right
root = BalanceNeeded( root, w, lh-rh );
break;
}
return root;
}
//A delete function
template <typename T>
avl_tree <T> *remove ( avl_tree <T>* root, const T& info ) {
#ifdef DEBUG
std::cout << "Current height of the tree is " << root->balance << std::endl;
std::cout << "Info to delete " << info << std::endl;
#endif
int m, inc[root->balance + 1], n(0), lh, rh;
avl_tree <T> *tmp(root), *crawler[root->balance + 1];
while ( root != None ) {
if ( root->data == info ) break;
m = (root->data < info);
inc[n] = m;
crawler[n++] = root;
root = root->Link[m];
}
if ( root == None ) return tmp; //Information not found :(
//if deleted tree has 1 or 0 branches
if ( root->Link[1] == None || root->Link[0] == None ) {
//Link deleted node's child to current link
int dir = root->Link[0] == None;
crawler[n-1]->Link[inc[n-1]] = root->Link[dir];
}
else {
//Tree to delete has 2 children, here we go...
crawler[n] = root; //Save the Node to be "deleted"
inc[n++] = 1;
avl_tree <T> *crown = root->Link[1]; //Go to the right subtree
//Travel as left as we can to crown new king
while ( crown->Link[0] != None ) {
crawler[n] = crown;
inc[n++] = 0;
crown = crown->Link[0];
}
//Found new king, simply swap info
root->data = crown->data;
//Create a link to the new tree
crawler[n-1]->Link[crawler[n-1] == root] = crown->Link[1];
//crawler[n-1] == root
//if the above while loop did not run once, this means the right
//child of the node to delete did not have a left child
//Can choose to delete the unsable tree or save it for later use
}
//Walk back up the tree and rebalance as needed
#ifdef DEBUG
std::cout << "Moonwalk...\n";
#endif //DEBUG
while ( --n >= 0 ) {
lh = height(crawler[n]->Link[inc[n]]);
rh = height(crawler[n]->Link[!inc[n]]);
crawler[n]->balance = 1 + avl_max(lh, rh);
crawler[n] = BalanceNeeded( crawler[n], lh > rh ? inc[n] : !inc[n], lh-rh );
if (n) crawler[n-1]->Link[inc[n-1]] = crawler[n];
}
#ifdef DEBUG
std::cout << "Tree balance is " << crawler[0]->balance
<< ". Tree data is " << crawler[0]->data << std::endl;
#endif
return crawler[0];
}
/*********FUNCTIONS*END*********/
}
int main() {
avl_tree <int> *tree(0);
for ( int r = 0; r < 1000000; ++r ) {
tree = AVL_TREE::insert( tree, r );
if ( r % 100000 == 0 ) {
for ( int f = r; f > 0; f >>= 4 )
tree = AVL_TREE::remove(tree, f);
}
}
delete [] tree;
return 0;
}
|