当前位置: 技术问答>linux和unix
数据结构中AVL数的具体构造哪位大侠介绍一下!谢谢
来源: 互联网 发布时间:2015-11-15
本文导语: 看linux,提到AVL,数据结构中AVL树的具体构造方法哪位大侠介绍一下!谢谢 | 1. 二叉平衡树(AVL)的定义 一棵AVL树或者是空树,或者左右子树都是AVL树,且左右子树的高度差部超过1. *有n个节点...
看linux,提到AVL,数据结构中AVL树的具体构造方法哪位大侠介绍一下!谢谢
|
1. 二叉平衡树(AVL)的定义
一棵AVL树或者是空树,或者左右子树都是AVL树,且左右子树的高度差部超过1.
*有n个节点的树的高度h=O(log(n)).因为具有O(log(n))的高度,就可以在O(log(n))时间里完成平衡树的
查找,删除,插入等操作.
AVL树的检索方法同二叉检索树(BST).
但AVL树经过插入和删除操作后, 可能会变得不平衡.因此必须作些额外的工作以保持平衡.一个重要的概
念就是平衡因子.我们在定义树结点结构的时候加入一个平衡因子域,定义如下:
typdef struct bnode {
datatype data;
int balance; // 平衡因子
struct bnode *lchild, *rchild;
}avl_node, *avl_nodeptr;
*节点p的平衡因子是它左右子树高度之差,所以在平衡条件下,它的值可以为(-1,0,1),当平衡因子为2,-2时,AVL失衡,必须调整已p为根的子树,以保持平衡.
2. AVL的插入
AVl的插入是先插入后调整的策略.
(1)像一般的检索树(BST)那样插入新节点x; //先插入
(2)沿着插入的路径回溯,修改平衡因子;
(3)如果发现失衡(balance= 2 or -2),旋转已p为根的子树,使之平衡.
大致的算法结构是这样的:
// bal 记录以p为根的子树的高度是否升高,如果升高,需要向上回溯.
bal = 0
void AVL_Insert(datatype data, avl_nodeptr p, int &bal)
//这里没有考虑效率,data数据没有使用指针传递
{
if (p == NULL) {
p = (avl_nodeptr)malloc(sizeof(avl_node));
p->data = data;
p->lchild = p->rchild = NULL;
p->balance = 0;
bal = 1;
return ;
}
if (data data) {
AVL_Insert(data,p->lchild,bal); // 插在左子树上
if(bal) Balance_Left(p,bal); // 如果p点升高,进行左平衡
}
else {
AVL_Insert(data,p->rchild,bal); //插在右子树上
if(bal) Balance_Right(p,bal); //如果p点降低,进行右平衡
}
}
需要注意的就是,不同情况的分析(如何旋转以降低树高),以及是否需要回溯(即上层树是否需要旋转,通过修改bal的值来实现,bal = 0 不回溯, 注意if(bal), 同时注意 AVL_Insert调用的bal的引用).
具体的调整算法思想很难用纯文字描述,用实例,画图是比较好的方法.google AVL 应该可以找到很多这方面的资料.
3. AVL树的构造
就是不断调用AVL插入的过程
4. AVL树的删除
类似AVL插入的分析.
一棵AVL树或者是空树,或者左右子树都是AVL树,且左右子树的高度差部超过1.
*有n个节点的树的高度h=O(log(n)).因为具有O(log(n))的高度,就可以在O(log(n))时间里完成平衡树的
查找,删除,插入等操作.
AVL树的检索方法同二叉检索树(BST).
但AVL树经过插入和删除操作后, 可能会变得不平衡.因此必须作些额外的工作以保持平衡.一个重要的概
念就是平衡因子.我们在定义树结点结构的时候加入一个平衡因子域,定义如下:
typdef struct bnode {
datatype data;
int balance; // 平衡因子
struct bnode *lchild, *rchild;
}avl_node, *avl_nodeptr;
*节点p的平衡因子是它左右子树高度之差,所以在平衡条件下,它的值可以为(-1,0,1),当平衡因子为2,-2时,AVL失衡,必须调整已p为根的子树,以保持平衡.
2. AVL的插入
AVl的插入是先插入后调整的策略.
(1)像一般的检索树(BST)那样插入新节点x; //先插入
(2)沿着插入的路径回溯,修改平衡因子;
(3)如果发现失衡(balance= 2 or -2),旋转已p为根的子树,使之平衡.
大致的算法结构是这样的:
// bal 记录以p为根的子树的高度是否升高,如果升高,需要向上回溯.
bal = 0
void AVL_Insert(datatype data, avl_nodeptr p, int &bal)
//这里没有考虑效率,data数据没有使用指针传递
{
if (p == NULL) {
p = (avl_nodeptr)malloc(sizeof(avl_node));
p->data = data;
p->lchild = p->rchild = NULL;
p->balance = 0;
bal = 1;
return ;
}
if (data data) {
AVL_Insert(data,p->lchild,bal); // 插在左子树上
if(bal) Balance_Left(p,bal); // 如果p点升高,进行左平衡
}
else {
AVL_Insert(data,p->rchild,bal); //插在右子树上
if(bal) Balance_Right(p,bal); //如果p点降低,进行右平衡
}
}
需要注意的就是,不同情况的分析(如何旋转以降低树高),以及是否需要回溯(即上层树是否需要旋转,通过修改bal的值来实现,bal = 0 不回溯, 注意if(bal), 同时注意 AVL_Insert调用的bal的引用).
具体的调整算法思想很难用纯文字描述,用实例,画图是比较好的方法.google AVL 应该可以找到很多这方面的资料.
3. AVL树的构造
就是不断调用AVL插入的过程
4. AVL树的删除
类似AVL插入的分析.
|
avl树就是平衡二叉树,特点:树中任意节点其左右子树的高度差不超过1。
向一个avl树中插入一个节点,失去平衡有4钟情况,参考《数据结构》严蔚敏、吴伟民,针对4种情况有不同的4种操作改为平衡的。
向一个avl树中插入一个节点,失去平衡有4钟情况,参考《数据结构》严蔚敏、吴伟民,针对4种情况有不同的4种操作改为平衡的。