学习笔记 AVL树
来源:互联网 发布:上海民族一厂淘宝官网 编辑:程序博客网 时间:2024/05/16 03:51
理想平衡与适度平衡
含有n个节点的二叉树高度以[logn]为上界,若树高恰好为[logn]则称为理想平衡树,完全二叉树就是其中之一。
适度平衡
而实际的二叉树关键码趋近与一侧的较多。在渐进意义下的平衡性才有意义。
局部性
在AVL树中,兄弟节点的高度相差不过1。而且还有:
- 经过单次动态修改操作后,至多只有O(1)的局部不再符合限制条件。
总可在O(logn)时间内,使O(1)处的不满足重新满足限制条件。
这点很重要,二叉树的顺序性是在中序遍历下确定的,所以只要在中序遍历不变的情况下可以认为两颗二叉树是等价的。
引入旋转调整的概念:
- zig
- zag
先前在二叉树中提到,孩子高度发生变化,父代很难发现其变化,所以在定义AVL模板类之前,给出关于平衡因子的宏定义。
- BalFac(v) = height(lc(v))-height(rc(v))
- |BalFac(v)|<=1
#define BalFac(x) (stature((x).lc)-stature((x).rc))#define AvlBalanced(x) ((-2<BalFac(x))&&(BalFac(x)<2))#define Balanced(x) (stature((x).lc)==stature((x).rc))
给出AVL模板类。
#include "BST.h"template<typename T>class AVL : public BST<T>{public: BinNodePosi(T) insert(const T& e); bool remove(const T& e); //其余沿用BST接口}
而插入算法不同于BST的一点就是插入一个新节点之后,历代祖先可能高度会发生变化,一但高度发生变化,平衡就会打破,所以重平衡是主要解决的问题。
由于前面局部性的定义,考察三个节点,v,p=v->parent,g=p->parent。一旦这个局部调整完成,全树的顺序性必然恢复。(这是为什么?)
宏定义
#define tallerChild(x) (stature((x)->lc)<stature((x)->rc)?x->rc:(//左边高 stature((x)->rc)<stature((x)->lc)?x->lc:(//右边高 IsChild(*(x))?x->lc:x->rc//等高的情况)))
先给出插入算法。
template<typename T>BinNodePosi(T) AVL<T>::insert(const T& e){ BinNodePosi(T) x = Search(e);//常规的搜索 if(x) return x;//如果x不存在则创建 BinNodePosi(T) xx = new BinNode<T>(e,_hot); _size++; for(BinNodePosi(T) g =_hot; g ; g = g->parent){//从_hot开始沿parent指针回溯 if(!AvlBalanced(*g)){//一旦发现不平衡 FromParentTo(*g)=rotateAt(tallerChild(tallerChild(g)));g->p->v break;//局部调整完毕则退出 } else//全树没有不平衡的点 updateHeight(g);//逐步更新高度 } return xx;//不论插入的点存不存在,总能返回。}
而删除算法则不一样,会出现以下的情况
调整之后,树高没有减少,P的某一祖先会有L-subT高度-1,而出现BalFac = -2的情况
template<typename T>bool AVL<T>::remove(const T& e){ BinNodePosi(T) &x = Search(e); if(!x) return false; removeAt(x,_hot);_size--; //重平衡 for(BinNodePosi(T) g = _hot;g;g=g->parent){ //没有办法提前退出 if(!AvlBalanced(*g)){ FromParentTo(*g) = rotateAt(tallerChild(tallerChild(g))); } } return true;}
统一重平衡算法
不论是插入或是删除算法,都需要调整一个子树,即v->p->g的结构,而3个节点构成的完全二叉树则完全可以重新构成一棵AVL树。
称之为“3+4重构”
template<typename T>BinNodePosi(T) BST<T>::connect34(BinNodePosi(T) a,BinNodePosi(T) b,BinNodePosi(T) c,BinNodePosi(T) T0,BinNodePosi(T) T1,BinNodePosi(T) T2,BinNodePosi(T) T3){ a->lc = T0; if(T0) T0->parent = a; a->rc = T1; if(T1) T1->parent = a; updateHeight(a); c->lc = T2; if(T2) T2->parent = c; c->rc = T3; if(T3) T3->parent = c; updateHeight(c); b->lc = a; b->rc = c; updateHeight(b); return b;}
有了3+4重构则可以完成先前zig以及zag旋转调整的思路。
template<typename T>BinNodePosi(T) BST<T>::rotateAt(BinNodePosi(T) v){ BinNodePosi(T) p = v->parent; BinNodePosi(T) g = p->parent; //单旋 if(IsLChild(*p)) if(IsLChild(*v)){ //zig操作 p->parent = g->parent; return connect34(v,p,g,v->lv,v->rc,g->lc,g->rc); } else{ //双旋 //zag-zig操作 v->parent = g->parent; return connect34(p,v,g,p->lc,p->rc,g->lc,g->rc); } else{ if(IsRChild(*v)){ //zag操作 p->parent = g->parent; return connect34(g,p,v,g->lc,g->rc,v->lc,v->rc); } else{ //zig-zag操作 v->parent = g->parent; return connect34(g,v,p,g->lc,g->rc,p->lc,p->rc); } }}
阅读全文
1 0
- 学习笔记 AVL树
- 数据结构学习笔记--AVL树
- AVL树学习笔记&模板
- AVL树的学习笔记
- 【学习笔记】AVL树的实现
- [学习笔记]AVL平衡二叉树
- avl树-《算法导论》学习笔记十三
- AVL Tree 学习笔记
- AVL Trees 学习笔记
- AVL树初学笔记
- 笔记-AVL树
- 数据结构学习笔记:B树、B+树、红黑树、AVL树
- 算法学习笔记(七) 平衡二叉树 AVL树
- 数据结构与算法分析学习笔记--第四章AVL树
- python数据结构学习笔记-2016-12-10-01-AVL树
- AVL树学习
- AVL 树 学习概要
- 学习笔记-AVL数和红黑树
- ARM内连汇编_asm_
- 基于Node.js的微信JS-SDK后端接口实现
- C++单链表选择排序
- 接入层负载均衡技术-lvs为何不能完全替代DNS轮询
- Enum --枚举妙用
- 学习笔记 AVL树
- IE下 jquery的fadeIn与fadeOut方法失效的BUG
- 1110. Complete Binary Tree (25)
- 度度熊回家 (模拟)
- 多线程阻塞类型
- Codeforces Round #428
- bzoj 1602: [Usaco2008 Oct]牧场行走(暴力LCA)
- python opencv入门 傅里叶变换(25)
- 代码REVIEW