加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 服务器 > 安全 > 正文

【数据结构】AVL树

发布时间:2021-03-31 11:36:55 所属栏目:安全 来源:网络整理
导读:1、AVL树简介 ????? AVL树本质上还是一棵二叉搜索树,又称高度平衡的二叉搜索树。它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度。对于二叉搜索树的介绍和实现,可查看本人上一篇博客。 2、AVL树的特点 1)本身首先是一棵二叉搜索树
副标题[/!--empirenews.page--]

1、AVL树简介

????? AVL树本质上还是一棵二叉搜索树,又称高度平衡的二叉搜索树。它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度。对于二叉搜索树的介绍和实现,可查看本人上一篇博客。

2、AVL树的特点

1)本身首先是一棵二叉搜索树。?

2)带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。

3)树中的每个左子树和右子树都是AVL树。

4)每个结点都有一个平衡因子,任一结点的平衡因子是-1,1.

注:结点的平衡因子 = 右子树高度 - 左子树高度

3、AVL树的效率

一棵AVL树有N个结点,其高度可以保持在lgN,插入/删除/查找的时间复杂度也是lgN。

AVL树的复杂程度真是比二叉搜索树高了整整一个数量级――它的原理并不难弄懂,但要把它用代码实现出来还真的有点费脑筋。下面我们来看看AVL树实现的接口,通过三叉链进行结点的实现。

template<class?K,?class?V>
struct?AVLTreeNode//三叉链
{
?AVLTreeNode<K,?V>*?_left;
?AVLTreeNode<K,?V>*?_right;
?AVLTreeNode<K,?V>*?_parent;
?K?_key;
?V?_value;
?int?_bf;//右子树与左子树的高度差
?AVLTreeNode(const?K&?key?=?K(),?const?V&?value?=?V())//加上K()和V(),可缺省构造
??:_left(NULL)
??,?_right(NULL)
??,?_parent(NULL)
??,?_key(key)
??,?_value(value)
??,?_bf(0)
?{}
};
template<class?K,?class?V>
class?AVLTree
{
?typedef?AVLTreeNode<K,?V>?Node;
public:
?AVLTree()
??:_root(NULL)
?{}
?void?Insert(const?K&?key,?const?V&?value);
?Node*?Find(const?K&?key);
?int?Height();
?bool?IsBalance();
?void?PrintAVLTree();
private:
?Node*?_Find(Node*?root,?const?K&?key);
?void?_RotateL(Node*&?parent);
?void?_RotateR(Node*&?parent);
?void?_RotateLR(Node*&?parent);
?void?_RotateRL(Node*&?parent);
?int?_Height(Node*?root);
?bool?_IsBalance(Node*?root);
?void?_PrintAVLTree(Node*?root);
protected:
?Node*?_root;
};

下面对插入进行元素的分析:

1)判断树是否为空,为空时,新建根结点。

2)查找插入的key是否存在,存在就退出函数,不存在就执行3)。

3)找到插入key的位置,然后插入结点cur。

4)更新平衡因子:从cur开始向上其父结点进行更新平衡因子,如果结点的平衡因子不满足AVL树,进行旋转调节平衡因子。

template<class?K,class?V>
void?AVLTree<K,V>::Insert(const?K&?key,?const?V&?value)
{
?if?(_root?==?NULL)
?{
??_root?=?new?Node(key,?value);
??return;
?}
?if?(Find(key))//存在key
?{
??return;
?}
?Node*?prev?=?NULL;
?Node*?cur?=?_root;
?while?(cur)//插入key的位置cur
?{
??if?(key?<?cur->_key)
??{
???prev?=?cur;
???cur?=?cur->_left;
??}
??else?if?(key?>?cur->_key)
??{
???prev?=?cur;
???cur?=?cur->_right;
??}
?}
?cur?=?new?Node(key,?value);//插如结点cur
?if?(prev->_key?>?key)
?{
??prev->_left?=?cur;
??cur->_parent?=?prev;
?}
?else?if?(prev->_key?<?key)
?{
??prev->_right?=?cur;
??cur->_parent?=?prev;
?}
?//prev为cur的上一个结点,即为cur是prev的父亲结点
?prev?=?cur;
?cur?=?prev->_parent;
?while?(cur)
?{
??//更新平衡因子:从插如的cur开始向上更新平衡因子
??cur->_bf?=?_Height(cur->_right)?-?_Height(cur->_left);
??if?(cur->_bf?!=?-1?&&?cur->_bf?!=?1?&&?cur->_bf?!=?0)//不满足AVL树的结点,进行旋转调节平衡因子
??{//平衡因子为2时,一定存在右子树;平衡因子为-2时,一定存在左子树
????//左单旋:2?1(平衡因子)
????if?(cur->_bf?==?2?&&?cur->_right->_bf?==?1)
????{
?????_RotateL(cur);//引用传递
????}
????//右单旋:-2?-1
????else?if?(cur->_bf?==?-2?&&?cur->_left->_bf?==?-1)
????{
?????_RotateR(cur);
????}
????//左右旋转:-2?1
????else?if?(cur->_bf?==?-2?&&?cur->_left->_bf?==?1)
????{
?????_RotateLR(cur);
????}
????//右左旋转:2?-1
????else?if?(cur->_bf?==?2?&&?cur->_right->_bf?==?-1)
????{
?????_RotateRL(cur);
????}
??}
??prev?=?cur;
??cur?=?cur->_parent;
?}
}

进行旋转调节平衡因子,分四种情况:

(1)左单旋:cur的平衡因子为2,cur->_right的平衡因子为1。

(2)右单旋:cur的平衡因子为-2,cur->_left的平衡因子为-1。

(3)左右旋转:cur的平衡因子为-2,cur->_left的平衡因子为1。

(4)右左旋转:cur的平衡因子为-2,cur->_right的平衡因子为-1。

左右旋转和右左旋转可通过调用左单旋和右单旋进行,注意结束后重置平衡因子。

如果不是很清楚,可以自己画图进行分析。

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读