普通的binary Search Tree的大量插入删除操作会造成树的不平衡,使得查找等操作效率不再为O(logn)。
AVLTree能够保证插入,删除,查找等操作在O(logn)内完成。
组成AVLTree的最少节点数与斐波那契数列的关系。
AVLTree的插入操作完成插入后需要更新节点的高度信息,并重新平衡此树, 找到发现问题的节点(imbalance factor == 2),并平衡以此节点为根节点的子树,然后新平衡树的根节点的祖先节点不需要更新, 因为平衡旋转后与插入前树的高度一样。
#ifndef AVL_TREE_H
#define AVL_TREE_H
#include <algorithm>
#include <iostream>
using namespace std;
template<class Comparable>
class AVLTree {
public:
// 优化代码,使得赋值操作简便
friend void swap(AVLTree &, AVLTree &);
AVLTree() : root(nullptr) { }
AVLTree(const AVLTree &rhs) : root(nullptr)
{
root = clone(rhs);
}
~AVLTree()
{
makeEmpty();
}
// deep copy
AVLTree &operator=(const AVLTree &rhs)
{
AVLTree copy = rhs;
swap(*this, copy); // just swap like a pointer,
return *this; // will call destructor when the method exits
}
AVLTree &operator=(AVLTree rhs) // 避免了自赋值情况
{
std::swap(root, rhs.root);
return *this;
}
// find the smallest item in the tree
// Throw UnderflowException if empty
const Comparable &findMin() const
{
if(isEmpty())
throw UnderflowException();
return findMin(root)->element;
}
const Comparable & findMax( ) const
{
if( isEmpty( ) )
throw UnderflowException();
return findMax( root )->element;
}
bool isEmpty() const
{
return root == nullptr;
}
// return true if x is in the tree
bool contains(const Comparable &x) const
{
return contains(x, root);
}
void makeEmpty()
{
makeEmpty(root);
}
// insert x into the tree, duplicates are ignored.
void insert(const Comparable &x)
{
insert(x, root);
}
void remove(const Comparable &x)
{
remove(x, root);
}
// print the tree contents in sorted order
void printTree() const
{
if(isEmpty())
cout << "Empty tree." << endl;
else
printTree(root);
}
private:
struct AVLNode
{
Comparable element;
AVLNode *left;
AVLNode *right;
int height;
AVLNode(const Comparable &ele, AVLNode *lt, AVLNode *rt, int h = 0)
: element(ele), left(lt), right(rt), height(h) { }
};
AVLNode *root;
static const int ALLOWED_IMBALANCE = 1; // imbalanced factor
/**
* Internal method to make subtree empty.
*/
void makeEmpty( AVLNode * & t )
{
if( t != nullptr )
{
makeEmpty( t->left );
makeEmpty( t->right );
delete t;
}
t = nullptr;
}
/*
* Assume t is balanced or within one of being balanced
* there are 4 situations for balance
*/
void balance(AVLNode *&t)
{
if(t == nullptr)
return;
if(height(t->left) - height(t->right) > ALLOWED_IMBALANCE)
if(height(t->left->left) >= height(t->left->right))
rotateWithLeftChild(t);
else
doubleWithLeftChild(t);
else
if(height(t->right) - height(t->left) > ALLOWED_IMBALANCE)
if(height(t->right->right) >= height(t->right->left))
rotateWithRightChild(t);
else
doubleWithRightChild(t);
// update the current node's height
t->height = max(height(t->left), height(t->right)) + 1;
}
int height(AVLNode *t) const
{
return t == nullptr ? -1 : t->height; // set the height of nullptr-node to -1.
}
int max(int lhs, int rhs) const
{
return lhs > rhs ?lhs : rhs;
}
/*
* Rotate binary tree node with left child.
* For AVL trees, this is a single rotation for left-left rotation
* update heights, then set new root.
* The height Only node k1 and k2 will be changed.
*/
void rotateWithLeftChild(AVLNode *&k2)
{
AVLNode *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max(height(k2->left), height(k2->right)) + 1;
k1->height = max(height(k1->left), k2->height) + 1;
k2 = k1; // update root node
}
/*
* Rotate binary tree node with right child.
* For a AVLtree ,this is a single rotation for right-right rotation.
* update heights, then set new root.
*/
void rotateWithRightChild(AVLNode *&k1)
{
AVLNode *k2 = k1->right;
k1->right = k2->left;
k2->left = k1;
k1->height = max( height( k1->left ), height( k1->right ) ) + 1;
k2->height = max( height( k2->right ), k1->height ) + 1;
k1 = k2;
}
/*
* Double rotate binary tree node: first left child
* for insert into leftChild's rightSubTree left-right
*/
void doubleWithLeftChild(AVLNode *&k3)
{
rotateWithRightChild(k3->left);
rotateWithLeftChild(k3);
}
/*
* Double rotate with right child.
* for insert into rightChild's leftSubTree right-left
*/
void doubleWithRightChild(AVLNode *&k1)
{
rotateWithLeftChild(k1->right);
rotateWithRightChild(k1);
}
/*
* Internal method to insert into a subtree. use recursive method.
* x is the item to insert
* t is the node that roots the subtree.
* set the new root of the subtree.
*/
void insert(const Comparable &x, AVLNode * &t)
{
if(t == nullptr)
t = new AVLNode(x, nullptr, nullptr);
else if(x < t->element)
insert(x, t->left);
else if(t->element < x)
insert(x, t->right);
else
;
balance(t); // make tree a AVLTree and update height
// use recursive insertion algorithm to backfrom insertion node to root node
// while find a node that violate AVLTree (balance |factor| >=2), ,then balance the node.
// after balance that node ,the other father node will be balanced automaticly
}
void remove(const Comparable &x, AVLNode *&t)
{
if(t == nullptr)
return;
if(x < t->element)
remove(x, t->left);
else if(t->element < x)
remove(x, t->right);
else if(t->left != nullptr && t->right != nullptr) {
t->element = findMin(t->right)->element;
remove(x, t->right);
}
else {
AVLNode *olfNode = t;
t = (t->left != nullptr) ? t->left : t->right;
delete oldNode;
}
balance(t);
}
/**
* Internal method to print a subtree rooted at t in sorted order.
*/
void printTree( AVLNode *t ) const
{
if( t != nullptr )
{
printTree( t->left );
cout << t->element << endl;
printTree( t->right );
}
}
/*
* Internal method to find the smallest item in a subtree t
* return node containing the smallest item
*/
AVLNode *findMin(AVLNode *t) const
{
if(t == nullptr)
return nullptr;
if(t->left == nullptr)
return t;
return findMin(t->left);
}
/**
* Internal method to find the largest item in a subtree t.
* Return node containing the largest item.
*/
AVLNode * findMax( AVLNode *t ) const
{
if( t != nullptr )
while( t->right != nullptr )
t = t->right;
return t;
}
/**
* Internal method to clone subtree.
*/
AVLNode * clone( AVLNode *t ) const
{
if( t == nullptr )
return nullptr;
else
return new AvlNode{ t->element, clone( t->left ), clone( t->right ), t->height };
}
};
inline void swap(AVLTree &lhs, AVLTree &rhs);
inline void swap(AVLTree &lhs, AVLTree &rhs)
{
using std::swap;
swap(lhs.root, rhs.root);
}
#endif
下面为测试代码:
#include"AVLTree.h"
#include<stdlib.h>
#include<time.h>
#include<vector>
int main()
{
AVLTree<int> tree1;
srand(time(nullptr));
vector<int> randomTreeElem;
int nodeNum = 10;
while (nodeNum--)
randomTreeElem.push_back(rand() % 50);
cout << "Test number are: " << endl;
for (auto i : randomTreeElem)
cout << i << ' ';
cout << endl;
for_each(randomTreeElem.begin(), randomTreeElem.end(), [&tree1](int elem) { tree1.insert(elem); });
cout << "LevelTraversal of the AVLTree are: \n";
tree1.printTree();
cout << endl;
return 0;
}
本测试随机生成了10个节点的AVLTree,然后打印tree, printTree是中序遍历tree,所以会得到递增的打印序列。
以下为测试结果: