# AVL树的实现（源码）

AVLTree

http://www.staroceans.com/AVLTree.htm

This is first edition of my AVL Tree and I never expect it takes so long as almost one week to finish! Of course
it is partly because of Christmas when I was continually interrupt by the earthly issues such as visiting a
friend and wasting some meaningful time on meaningless matters.
C.The idea of program

By adding a little piece of code in "insert" method of BST, I actually try to do the keeping-balance

job along the "insert" operation from bottom-up which always keep each node up-to-date balanced. It

is believed by me the best solution to implement it. Unfortunately I have to keep the clue of the

path which leads to the newly-inserted node at leaf position. So, I was obliged to add one more

field in node---"inLeft" which is a boolean value indicating which side the path goes down to the

new leaf. Along with it is the "height" data which is the absolute height of a subtree rooted as

current node. I thought it is a cheating in pseudo code by using "balancing-factor" as instead of

using "real height" of each node. But after finishing the program with several big changes, I

realized I might do some stupid things on assuming that absolute height is necessary. Maybe in

second edition I should combine both "inLeft" and "height" together with "factor"----balancing

factor.



// Binary tree node abstract class
template <class Elem> class BinNode {
public:
// Return the node's element
virtual Elem& val() = 0;
// Set the node's element
virtual void setVal(const Elem&) = 0;
// Return the node's left child
virtual BinNode* left() const = 0;
// Set the node's left child
virtual void setLeft(BinNode*) = 0;
// Return the node's right child
virtual BinNode* right() const = 0;
// Set the node's right child
virtual void setRight(BinNode*) = 0;
// Return true iff the node is a leaf
virtual bool isLeaf() = 0;
//my personal preference
virtual BinNode<Elem>* getSon(bool isLeft)const=0;
//my personal preference
virtual void setSon(BinNode<Elem>* son, bool isLeft)=0;
};

// Binary tree node class
template <class Elem>
class BinNodePtr : public BinNode<Elem> {
private:
Elem it;                     // The node's value
BinNodePtr* lc;              // Pointer to left child
BinNodePtr* rc;              // Pointer to right child
public:
// Two constructors -- with and without initial values
BinNodePtr() { lc = rc = NULL; }
BinNodePtr(Elem e, BinNodePtr* l =NULL,
BinNodePtr* r =NULL)
{ it = e; lc = l; rc = r; }
~BinNodePtr() {}             // Destructor
Elem& val() { return it; }
void setVal(const Elem& e) { it = e; }
inline BinNode<Elem>* left() const { return lc; }
void setLeft(BinNode<Elem>* b) { lc = (BinNodePtr*)b; }
inline BinNode<Elem>* right() const { return rc; }
void setRight(BinNode<Elem>* b) { rc = (BinNodePtr*)b; }
bool isLeaf() { return (lc == NULL) && (rc == NULL); }
BinNode<Elem>* getSon(bool isLeft)const {return isLeft?lc:rc;}
void setSon(BinNode<Elem>* son, bool isLeft)
{
isLeft?setLeft(son):setRight(son);
}
};

template <class Elem>
class AVLNodePtr : public BinNode<Elem>
{
protected:
Elem it;                     // The node's value
AVLNodePtr* lc;              // Pointer to left child
AVLNodePtr* rc;              // Pointer to right child
int height;
bool inLeft;
public:
// Two constructors -- with and without initial values
AVLNodePtr() { lc = rc = NULL; height=1; inLeft=true; }
AVLNodePtr(Elem e, AVLNodePtr<Elem>* l =NULL,
AVLNodePtr<Elem>* r =NULL, int newHeight=1)
{ it = e; lc = l; rc = r; height=newHeight; inLeft=true;}
~AVLNodePtr() {}             // Destructor
Elem& val() { return it; }
void setVal(const Elem& e) { it = e; }
BinNode<Elem>* left() const { return lc; }
void setLeft(BinNode<Elem>* b) { lc = (AVLNodePtr*)b; }
inline BinNode<Elem>* right() const { return rc; }
void setRight(BinNode<Elem>* b) { rc = (AVLNodePtr*)b; }
bool isLeaf() { return (lc == NULL) && (rc == NULL); }
void setHeight(int newHeight){height=newHeight;}
int getHeight(){return height;}
BinNode<Elem>* getSon(bool isLeft)const {return isLeft?lc:rc;}
bool getSide() const {return inLeft;}
void setSide(bool isLeft){ inLeft=isLeft;}
void setSon(BinNode<Elem>* son, bool isLeft)
{
isLeft?setLeft(son):setRight(son);
}

};

// This file includes all of the pieces of the BST implementation

#include "dictionary.h"

#include "binnode.h"

// Binary Search Tree implementation for the Dictionary ADT
template <class Key, class Elem, class KEComp, class EEComp>
class BST : public Dictionary<Key, Elem, KEComp, EEComp> {
protected:
BinNode<Elem>* root;   // Root of the BST
int nodecount;         // Number of nodes in the BST
// Private "helper" functions
void clearhelp(BinNode<Elem>*);
BinNode<Elem>* inserthelp(BinNode<Elem>*, const Elem&);
BinNode<Elem>* deletemin(BinNode<Elem>*, BinNode<Elem>*&);
BinNode<Elem>* removehelp(BinNode<Elem>*, const Key&,
BinNode<Elem>*&);
bool findhelp(BinNode<Elem>*, const Key&, Elem&) const;
void printhelp(BinNode<Elem>*, int) const;
public:
BST() { root = NULL; nodecount = 0; }  // Constructor
~BST() { clearhelp(root); }            // Destructor
void clear()
{ clearhelp(root); root = NULL; nodecount = 0; }
bool insert(const Elem& e) {
root = inserthelp(root, e);
nodecount++;
return true;
}
bool remove(const Key& K, Elem& e) {
BinNode<Elem>* t = NULL;
root = removehelp(root, K, t);
if (t == NULL) return false;  // Nothing found
e = t->val();
nodecount--;
delete t;
return true;
}
bool removeAny(Elem& e) { // Delete min value
if (root == NULL) return false; // Empty tree
BinNode<Elem>* t;
root = deletemin(root, t);
e = t->val();
delete t;
nodecount--;
return true;
}
bool find(const Key& K, Elem& e) const
{ return findhelp(root, K, e); }
int size() { return nodecount; }
void print() const {
if (root == NULL) cout << "The BST is empty./n";
else printhelp(root, 0);
}
};

template <class Key, class Elem, class KEComp, class EEComp>
void BST<Key, Elem, KEComp, EEComp>::
clearhelp(BinNode<Elem>* subroot) {
if (subroot == NULL) return;
clearhelp(subroot->left());
clearhelp(subroot->right());
delete subroot;
}

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>::
inserthelp(BinNode<Elem>* subroot, const Elem& val) {
if (subroot == NULL)            // Empty tree: create node
return (new BinNodePtr<Elem>(val, NULL, NULL));
if (EEComp::lt(val, subroot->val())) // Insert on left
subroot->setLeft(inserthelp(subroot->left(), val));
else subroot->setRight(inserthelp(subroot->right(), val));
return subroot;  // Return subtree with node inserted
}

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>::
deletemin(BinNode<Elem>* subroot, BinNode<Elem>*& min) {
if (subroot->left() == NULL) { // Found min
min = subroot;
return subroot->right();
}
else {                         // Continue left
subroot->setLeft(deletemin(subroot->left(), min));
return subroot;
}
}

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>::
removehelp(BinNode<Elem>* subroot, const Key& K,
BinNode<Elem>*& t) {
if (subroot == NULL) return NULL; // Val is not in tree
else if (KEComp::lt(K, subroot->val())) // Check left
subroot->setLeft(removehelp(subroot->left(), K, t));
else if (KEComp::gt(K, subroot->val())) // Check right
subroot->setRight(removehelp(subroot->right(), K, t));
else {                           // Found it: remove it
BinNode<Elem>* temp;
t = subroot;
if (subroot->left() == NULL)       // Only a right child
subroot = subroot->right();      //  so point to right
else if (subroot->right() == NULL) // Only a left child
subroot = subroot->left();       //  so point to left
else {                    // Both children are non-empty
subroot->setRight(deletemin(subroot->right(), temp));
Elem te = subroot->val();
subroot->setVal(temp->val());
temp->setVal(te);
t = temp;
}
}
return subroot;
}

template <class Key, class Elem, class KEComp, class EEComp>
bool BST<Key, Elem, KEComp, EEComp>:: findhelp(
BinNode<Elem>* subroot, const Key& K, Elem& e) const {
if (subroot == NULL) return false;         // Empty tree
else if (KEComp::lt(K, subroot->val()))    // Check left
return findhelp(subroot->left(), K, e);
else if (KEComp::gt(K, subroot->val()))    // Check right
return findhelp(subroot->right(), K, e);
else { e = subroot->val();  return true; } // Found it
}

template <class Key, class Elem, class KEComp, class EEComp>
void BST<Key, Elem, KEComp, EEComp>::
printhelp(BinNode<Elem>* subroot, int level) const {
if (subroot == NULL) return;          // Empty tree
printhelp(subroot->left(), level+1);  // Do left subtree
for (int i=0; i<level; i++)           // Indent to level
cout << "  ";
cout << subroot->val() << "/n";       // Print node value
printhelp(subroot->right(), level+1); // Do right subtree
}



// The Dictionary abstract class.  KEComp compares a key
// and an element. EEComp compares two elements.
template <class Key, class Elem, class KEComp, class EEComp>
class  Dictionary {
public:
// Reinitialize dictionary
virtual void clear() = 0;
// Insert an element.  Return true if insert is
// successful, false otherwise.
virtual bool insert(const Elem&) = 0;
// Remove some element matching Key.  Return true if such
// exists, false otherwise.  If multiple entries match
// Key, an arbitrary one is removed.
virtual bool remove(const Key&, Elem&) = 0;
// Remove and return an arbitrary element from dictionary.
// Return true if some element is found, false otherwise.
virtual bool removeAny(Elem&) = 0;
// Return a copy of some Elem matching Key.  Return true
// if such exists, false otherwise.  If multiple elements
// match Key, return an arbitrary one.
virtual bool find(const Key&, Elem&) const = 0;
// Return the number of elements in the dictionary.
virtual int size() = 0;
};


//This is the element of login system

class KEComp
{
public:
static bool lt(int key, int elem) {return key<elem;}
static bool eq(int key, int elem) {return key==elem;}
static bool gt(int key, int elem) {return key>elem;}
};

class EEComp
{
public:
static bool lt(int e1, int e2)
{ return e1<e2;}
static bool eq(int e1, int e2)
{ return e1==e2;}
static bool gt(int e1, int e2)
{ return e1>e2;}
};

#include "BST.h"

template<class Elem>
struct Descriptor
{
BinNode<Elem>* parent;
bool isRoot;
bool isLeft;
bool isSingle;
bool left2right;
};

template<class Key, class Elem, class KEComp, class EEComp>
class AVL: public BST<Key, Elem, KEComp, EEComp>
{
protected:
//	BinNode<Elem>* startPtr;
void clearhelp(BinNode<Elem>*);
BinNode<Elem>* inserthelp(BinNode<Elem>*, const Elem&);
BinNode<Elem>* removehelp(BinNode<Elem>*, const Key&,
BinNode<Elem>*&);
bool findhelp(BinNode<Elem>*, const Key&, Elem&) const;
void printhelp(BinNode<Elem>*, int) const;
void updateHeight(BinNode<Elem>*& subroot);
int  getFactor(BinNode<Elem>* subroot);
int getTreeHeight(BinNode<Elem>* subroot);
BinNode<Elem>* singleRotate(BinNode<Elem>* parent, bool isRoot, bool left2right);
BinNode<Elem>* doubleRotate(BinNode<Elem>* parent, bool isRoot, bool left2right);
void checkDir(BinNode<Elem>* subroot, bool& isSingle, bool& left2right);
BinNode<Elem>* doDouble(BinNode<Elem>* oldRoot, bool left2right);

public:
AVL() { root = NULL; nodecount = 0; }  // Constructor
~AVL() { clearhelp(root); root=NULL; }            // Destructor
bool insert(const Elem& e)
{
root = inserthelp(root, e);
nodecount++;
return true;
}
};

//do not use recursive!!!!!
template <class Key, class Elem, class KEComp, class EEComp>
int AVL<Key, Elem, KEComp, EEComp>::getTreeHeight(BinNode<Elem>* subroot)
{
AVLNodePtr<Elem>* ptr, *l, *r;
int newHeight, lHeight, rHeight;//, factor;//, sonFactor;

if (subroot==NULL)
{
return 0;
}

ptr=(AVLNodePtr<Elem>*)subroot;
l=(AVLNodePtr<Elem>*)ptr->left();
r=(AVLNodePtr<Elem>*)ptr->right();
if (l==NULL)
{
lHeight=0;
}
else
{
lHeight=l->getHeight();
}
if (r==NULL)
{
rHeight=0;
}
else
{
rHeight=r->getHeight();
}
newHeight=1+(lHeight>rHeight?lHeight:rHeight);
return newHeight;
}

template <class Key, class Elem, class KEComp, class EEComp>
void AVL<Key, Elem, KEComp, EEComp>::adjustHeight(BinNode<Elem>* subroot)
{
int height;
if (subroot==NULL)
{
return;
}
height=getTreeHeight(subroot);
((AVLNodePtr<Elem>*)(subroot))->setHeight(height);
}

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* AVL<Key, Elem, KEComp, EEComp>::doDouble(BinNode<Elem>* oldRoot,
bool left2right)
{
BinNode<Elem> *small, *mid, *big,*t1,*t2,*t3,*t4;
if (left2right)
{
big=oldRoot;//the root;
small=oldRoot->left();
mid=small->right();
t1=small->left();
t2=mid->left();
t3=mid->right();
t4=big->right();
}
else
{
small=oldRoot;
big=small->right();
mid=big->left();
t1=small->left();
t2=mid->left();
t3=mid->right();
t4=big->right();
}
mid->setLeft(small);
mid->setRight(big);
small->setLeft(t1);
small->setRight(t2);
big->setLeft(t3);
big->setRight(t4);
return mid;
}

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* AVL<Key, Elem, KEComp, EEComp>::doubleRotate(BinNode<Elem>* parent,
bool isRoot, bool left2right)
{
BinNode<Elem>* oldRoot;
bool isLeft;

if (isRoot)
{
oldRoot=parent;
root=doDouble(oldRoot, left2right);

return root;//because we need parent return as real root
}
else
{
isLeft=((AVLNodePtr<Elem>*)parent)->getSide();
oldRoot=parent->getSon(isLeft);
parent->setSon(doDouble(oldRoot, left2right), isLeft);
return parent;
}
}

//if isRoot, we don't need isLeft, it is useful when it is not root and
//we need to know which son it is in
template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* AVL<Key, Elem, KEComp, EEComp>::singleRotate(BinNode<Elem>* parent,
bool isRoot, bool left2right)
{
BinNode<Elem>* oldRoot=parent, *son, *t1;
bool isLeft=((AVLNodePtr<Elem>*)parent)->getSide();

if (isRoot)
{
son=parent->getSon(isLeft);
t1=son->getSon(!left2right);
son->setSon(parent, !left2right);
parent->setSon(t1, left2right);
//because parent is at lower level now, we need adjust parent first!!!

root=son;
return son;//because now, we need return son as parent;
}
else
{
//for non-root rotation, parent doesn't change!!!!!
//it is now very concise!!
oldRoot=parent->getSon(isLeft);
son=oldRoot->getSon(left2right);//this is the trick!
t1=son->getSon(!left2right);
parent->setSon(son, isLeft);
oldRoot->setSon(t1, left2right);
son->setSon(oldRoot, !left2right);
//sequence is very important!!!
return parent;
}

}

//check the direction of rotation by returning value in reference
template<class Key, class Elem, class KEComp, class EEComp>
void AVL<Key, Elem, KEComp, EEComp>::checkDir(BinNode<Elem>* subroot,
bool& isSingle, bool& left2right)
{
BinNode<Elem>* son;
int parentFactor, sonFactor;
bool isLeft;
isLeft=((AVLNodePtr<Elem>*)subroot)->getSide();
son=subroot->getSon(isLeft);
parentFactor=getFactor(subroot);
sonFactor=getFactor(son);
isSingle=parentFactor*sonFactor>0;//same sign
left2right=parentFactor>0;
}

//if isroot, isLeft will be ignored.
template <class Key, class Elem, class KEComp, class EEComp>
void AVL<Key, Elem, KEComp, EEComp>::adjust(BinNode<Elem>*& subroot, bool isRoot)
{
BinNode<Elem>* temp;
bool isSingle, left2right, isLeft;
if (isRoot)
{
temp=subroot;
}
else
{
//use its son to check
isLeft=((AVLNodePtr<Elem>*)subroot)->getSide();
temp=subroot->getSon(isLeft);
}

checkDir(temp, isSingle, left2right);
if (isSingle)
{
//it helps reading and for singleRotate isLeft is ignored when it is isRoot
subroot=singleRotate(subroot, isRoot, left2right);
}
else
{
subroot=doubleRotate(subroot, isRoot, left2right);
}
}

template <class Key, class Elem, class KEComp, class EEComp>
int AVL<Key, Elem, KEComp, EEComp>::getFactor(BinNode<Elem>* subroot)
{
int lHeight, rHeight;
AVLNodePtr<Elem>* ptr, *l, *r;
if (subroot==NULL)
{
return 0;
}
ptr=(AVLNodePtr<Elem>*)subroot;
l=(AVLNodePtr<Elem>*)(ptr->left());
r=(AVLNodePtr<Elem>*)(ptr->right());
if (l==NULL)
{
lHeight=0;
}
else
{
lHeight= l->getHeight();
}
if (r==NULL)
{
rHeight=0;
}
else
{
rHeight=r->getHeight();
}
return lHeight-rHeight;
}

template <class Key, class Elem, class KEComp, class EEComp>
void AVL<Key, Elem, KEComp, EEComp>::updateHeight(BinNode<Elem>*& subroot)
{
int factor, sonFactor;
bool isLeft;
BinNode<Elem> *son;
if (subroot==NULL)
{
return;
}

factor=getFactor(subroot);

isLeft=((AVLNodePtr<Elem>*)subroot)->getSide();
son=subroot->getSon(isLeft);
sonFactor=getFactor(son);
//first situation: the first 2/-2 we meet from bottom-up
if ((factor==2||factor==-2)&&subroot==root)
{
//a special case!!! as we search from bottom up
//we may wait to adjust until we reach its father
//the father happens to be root. But it is not a
if (sonFactor==1||sonFactor==-1)
{
}
else
{
}
}
else
{

if (sonFactor==2||sonFactor==-2)
{
}
}
}

template <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* AVL<Key, Elem, KEComp, EEComp>::inserthelp(BinNode<Elem>* subroot,
const Elem& val)
{
if (subroot == NULL)            // Empty tree: create node
{
return (new AVLNodePtr<Elem>(val, NULL, NULL, 1));
}
if (EEComp::lt(val, subroot->val())) // Insert on left
{
((AVLNodePtr<Elem>*)subroot)->setSide(true);
subroot->setLeft(inserthelp(subroot->left(), val));
updateHeight(subroot);
}
else
{
((AVLNodePtr<Elem>*)subroot)->setSide(false);
subroot->setRight(inserthelp(subroot->right(), val));
updateHeight(subroot);
}
return subroot;  // Return subtree with node inserted
}

template <class Key, class Elem, class KEComp, class EEComp>
void AVL<Key, Elem, KEComp, EEComp>::clearhelp(BinNode<Elem>* subroot)
{
if (subroot == NULL)
{
return;
}
clearhelp(subroot->left());
clearhelp(subroot->right());
delete subroot;
}

#include <iostream>
#include <time.h>
#include "AVLTree.h"
#include "Elem.h"

using namespace std;

int main()
{
int num;
AVL<int, int, KEComp, EEComp> A;
//srand(time(0));
for (int i=0; i<25; i++)
{
cout<<"===================";
num=rand()%100+12;
cout<<"insert number "<<num<<endl;
A.insert(num);
A.print();
}
return 0;
}


===================insert number 53
53
===================insert number 79
53
79
===================insert number 46
46
53
79
===================insert number 12
12
46
53
79
===================insert number 81
12
46
53
79
81
===================insert number 36
12
36
46
53
79
81
===================insert number 90
12
36
46
53
79
81
90
===================insert number 70
12
36
46
53
70
79
81
90
===================insert number 74
12
36
46
53
70
74
79
81
90
===================insert number 76
12
36
46
53
70
74
76
79
81
90
===================insert number 17
12
17
36
46
53
70
74
76
79
81
90
===================insert number 57
12
17
36
46
53
57
70
74
76
79
81
90
===================insert number 93
12
17
36
46
53
57
70
74
76
79
81
90
93
===================insert number 39
12
17
36
39
46
53
57
70
74
76
79
81
90
93
===================insert number 73
12
17
36
39
46
53
57
70
73
74
76
79
81
90
93
===================insert number 103
12
17
36
39
46
53
57
70
73
74
76
79
81
90
93
103
===================insert number 107
12
17
36
39
46
53
57
70
73
74
76
79
81
90
93
103
107
===================insert number 54
12
17
36
39
46
53
54
57
70
73
74
76
79
81
90
93
103
107
===================insert number 39
12
17
36
39
39
46
53
54
57
70
73
74
76
79
81
90
93
103
107
===================insert number 48
12
17
36
39
39
46
48
53
54
57
70
73
74
76
79
81
90
93
103
107
Press any key to continue




• 本文已收录于以下专栏：

## AVL树及C语言实现

• IT_PCode
• 2014年03月28日 23:34
• 1868

## AVL树的旋转图解和简单实现

AVL树是带有平衡条件的查找二叉树。这个平衡条件要容易保持，而且他要保证树的深度为O(logN)原文地址：http://blog.csdn.net/qq_25806863/article/detail...
• qq_25806863
• 2017年07月07日 18:03
• 481

## 自己动手实现数据结构——AVL树（C++实现）

• sshhiixx
• 2015年08月10日 13:06
• 1438

## AVL树的java实现

AVL树的定义自己百度去，这里给出自己用java的一个实现。 package test; /** * @时间 2014-3-30 * @version 0.1 * @encode UTF-8...
• dahlwuyn
• 2014年03月31日 16:07
• 4353

## C++模板实现的AVL树

1 AVL树的定义 AVL树是一种自平衡二叉排序树，它的特点是任何一个节点的左子树高度和右子树的高度差在-1,0,1三者之间。AVL树的任何一个子树都是AVL树。 2 AVL树的实现 AVL树本质是一...
• zhuhuangtianzi
• 2014年11月03日 18:40
• 1002

## AVL树实现与分析

AVL是高度平的二叉搜索树，它能降低二叉树的高度，减少树的平均搜索长度
• he_shuai20
• 2017年04月27日 23:50
• 868

## 平衡二叉搜索树（AVL树）的原理及实现源代码（有图文详解和C++、Java实现代码）

• u013149325
• 2014年11月22日 21:46
• 1714

## AVL树原理通俗解释与例子

AVL（Adelson-Velskii and Landis）树是带有平衡条件（balance condition）的二叉查找树。 这个平衡条件必须容易保持，而且必须保证树的深度是O(logN)。 A...
• songzige
• 2016年04月21日 16:37
• 1003

## AVL树的C++实现 Implement of AVL tree

AVL是一种自平衡的二叉查找树。 不同于普通的二叉查找树之处在于：每个节点的左右子树高度差最多为1，故每个节点多了一个高度（height）属性。 其实现难点在于插入和删除时要检测节点高度差是否满足上述...
• showonstage1
• 2014年03月31日 22:51
• 1440

## Avl树的基本操作（c语言实现）

#include #include typedef struct AvlNode *Position; typedef struct AvlNode *AvlTree; typedef int El...
• Stephen_Curry_
• 2016年03月17日 16:42
• 1259

举报原因： 您举报文章：AVL树的实现（源码） 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)