平衡二叉树——AVL树的原理和实现

计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。

节点的平衡因子是它的左子树的高度减去它的右子树的高度(有时相反)。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。

以下图表以四列表示四种情况,每行表示在该种情况下要进行的操作。在左左和右右的情况下,只需要进行一次旋转操作;在左右和右左的情况下,需要进行两次旋转操作。


注意:其中左右和右左,先经过一次旋转变为左左和右右的情况,再进行第二次旋转。


插入

向AVL树插入可以通过如同它是未平衡的二叉查找树一样把给定的值插入树中,接着自底向上向根节点折回,于在插入期间成为不平衡的所有节点上进行旋转来完成。因为折回到根节点的路途上最多有1.44乘log n个节点,而每次AVL旋转都耗费恒定的时间,插入处理在整体上耗费O(log n) 时间。

删除

从AVL树中删除可以通过把要删除的节点向下旋转成一个叶子节点,接着直接剪除这个叶子节点来完成。因为在旋转成叶子节点期间最多有log n个节点被旋转,而每次AVL旋转耗费恒定的时间,删除处理在整体上耗费O(log n) 时间。

查找

可以像普通二叉查找树一样的进行,所以耗费O(log n)时间,因为AVL树总是保持平衡的。不需要特殊的准备,树的结构不会由于查找而改变。(这是与伸展树查找相对立的,它会因为查找而变更树结构。)

#include<iostream>
using namespace std;
struct TreeNode
	{
	int bf;
	int height;
	int data;
	TreeNode *leftchild;
	TreeNode *rightchild;
	TreeNode *parent;
	};
int max(int a, int b)
{
	return a>b?a:b;
}
template<class obj_s>
class AVLTree
{
public:
	TreeNode *root;
public:
	AVLTree()
	{
		root=NULL;
	}
	int getHeight(TreeNode *node);
	int reComHeight(TreeNode *root);//重新计算高度
	//四种旋转方式
	TreeNode* LLclockRotation(TreeNode* x);
	TreeNode* RRantiRotation(TreeNode* x);
	TreeNode* LRanti_clockRotation(TreeNode* x);
	TreeNode* RLclock_antiRotation(TreeNode* x);
	//
	TreeNode* reBalance(TreeNode* cur,int bf);
	//插入和删除
	TreeNode* insert(TreeNode* curr,TreeNode* prev,int num);
	TreeNode* findDelPosition(TreeNode* root,int key);
	//
	TreeNode* clearTarget(TreeNode* root);
	//
	void toPrint(TreeNode* root,int depth=0);
	//找待删除结点的前驱结点
	TreeNode* FindMin(TreeNode* least);
};
template<class obj_s>
int AVLTree<obj_s>::getHeight(TreeNode* node)
{  
    if(node) 
		return node->height;  
    else 
		return -1;  
}
template<class obj_s>
int AVLTree<obj_s>::reComHeight(TreeNode* root)
{  
    root->height = max(getHeight(root->leftchild), getHeight(root->rightchild)) + 1;  
    root->bf = getHeight(root->leftchild) - getHeight(root->rightchild);  
    return root->bf;  
} 
template<class obj_s>
TreeNode* AVLTree<obj_s>::LLclockRotation(TreeNode* x)
{  
    TreeNode* y = x->leftchild;  
    x->leftchild = y->rightchild;  
    if (y->rightchild) 
		y->rightchild->parent = x;  
    y->rightchild = x;  
    y->parent = x->parent;  
    x->parent = y;  
    reComHeight(x);  
    reComHeight(y);  
    return y;  
} 
template<class obj_s>
TreeNode* AVLTree<obj_s>::RRantiRotation(TreeNode* x){  
    TreeNode* y = x->rightchild;  
    x->rightchild = y->leftchild;  
    if (y->leftchild) 
		y->leftchild->parent = x;  
    y->leftchild = x;  
    y->parent = x->parent;  
    x->parent = y;  
    reComHeight(x);  
    reComHeight(y);  
    return y;  
}
template<class obj_s>
TreeNode* AVLTree<obj_s>::LRanti_clockRotation(TreeNode* x)
{
	x->leftchild = RRantiRotation(x->leftchild);  
    return LLclockRotation(x); 
}
template<class obj_s>
TreeNode* AVLTree<obj_s>::RLclock_antiRotation(TreeNode* x)  
{  
    x->rightchild = LLclockRotation(x->rightchild);  
    return RRantiRotation(x);  
} 
template<class obj_s>
TreeNode* AVLTree<obj_s>::reBalance(TreeNode* curr, int bf)
{  
    if(abs(bf)<2) 
		return curr;  
    else
	{  
        if(bf == -2)
		{  
            if (curr->rightchild->bf>0) 
				return RLclock_antiRotation(curr);  
            else 
				return RRantiRotation(curr);  
        }  
        else if(bf == 2)
		{  
            if (curr->leftchild->bf < 0)
				return LRanti_clockRotation(curr);  
            else 
				return LLclockRotation(curr);  
        }  
    }
	//return NULL;
}
template<class obj_s>
TreeNode* AVLTree<obj_s>::insert(TreeNode* curr, TreeNode* prev, int num){  
     int x = 0;  
    if (!curr)
	{  
        curr = (TreeNode*)malloc(sizeof(TreeNode));  
        curr->data = num;  
        curr->bf = 0;  
        curr->height = 0;  
        curr->parent = prev;  
        curr->leftchild = curr->rightchild = NULL;  
        x = num;  
    }  
    else if(num<(curr->data)) 
		curr->leftchild = insert(curr->leftchild, curr, num);  
    else if(num>(curr->data)) 
		curr->rightchild = insert(curr->rightchild, curr, num);  
    curr=reBalance(curr,reComHeight(curr));  
    return curr;  
}
template<class obj_s>
void AVLTree<obj_s>::toPrint(TreeNode* root, int depth)
{  
    if(root->rightchild)
		toPrint(root->rightchild, depth + 1);  
    for(int i = 0; i< depth; i++) 
		printf("\t");  
	printf("%d(%d,%d)\n", root->data,root->height, root->bf);  
    if (root->leftchild)
		toPrint(root->leftchild, depth + 1);  
} 
template<class obj_s>
TreeNode* AVLTree<obj_s>::FindMin(TreeNode* least){  
    if(!least->leftchild)
		return least;  
    else 
		FindMin(least->leftchild);  
}
template<class obj_s>
TreeNode* AVLTree<obj_s>::clearTarget(TreeNode* root){  
    TreeNode* par = root->parent, * temp = root;  
    if (root->leftchild&&root->rightchild){  
        temp = FindMin(root->rightchild);  
        root->data = temp->data;  
        root->rightchild = findDelPosition(root->rightchild, root->data);  
    }  
    else
	{  
        if (root->leftchild){  
            root->leftchild->parent = par;  
            if (par->leftchild == root) par->leftchild = root->leftchild;  
            else if (par->rightchild == root) par->rightchild = root->leftchild;  
            root = root->leftchild;  
        }  
        else if (root->rightchild){  
            root->rightchild->parent = par;//认可问题  
            if (par->leftchild == root) par->leftchild = root->rightchild;  
            else if (par->rightchild == root) par->rightchild = root->rightchild;  
            root = root->rightchild;  
        }  
        else root = NULL;//都为NULL  
        free(temp);  
    }  
    if (root) reComHeight(root);  
    return root;  
}
template<class obj_s>
TreeNode* AVLTree<obj_s>::findDelPosition(TreeNode* root, int key){  
    if(key == root->data) 
		root = clearTarget(root);  
    else if(key<root->data) 
		root->leftchild = findDelPosition(root->leftchild, key);  
    else if(key>root->data) 
		root->rightchild = findDelPosition(root->rightchild, key);  
    if(root) 
		root = reBalance(root, reComHeight(root));  
    return root;  
  
}
int main()
{  
  
    int temp[10] = { 40, 60, 20, 80, 50, 30, 10, 70, 25,65 };  
    AVLTree<int> avl;
    for (int i = 0; i < 10; i++) 
		avl.root = avl.insert(avl.root, avl.root, temp[i]);  
	//avl.findDelPosition(avl.root, 40); 删除操作
    avl.toPrint(avl.root);  
	system("pause");
	return 0;
} 

结果:
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值