收藏 分享(赏)

平衡二叉树的生成过程.doc

上传人:kpmy5893 文档编号:8158052 上传时间:2019-06-11 格式:DOC 页数:8 大小:96.50KB
下载 相关 举报
平衡二叉树的生成过程.doc_第1页
第1页 / 共8页
平衡二叉树的生成过程.doc_第2页
第2页 / 共8页
平衡二叉树的生成过程.doc_第3页
第3页 / 共8页
平衡二叉树的生成过程.doc_第4页
第4页 / 共8页
平衡二叉树的生成过程.doc_第5页
第5页 / 共8页
点击查看更多>>
资源描述

1、二叉排序树变成平衡二叉树对于二叉查找树,尽管查找、插入及删除操作的平均运行时间为 O(logn),但是它们的最差运行时间都是 O(n),原因在于对树的形状没有限制。平衡二叉树又称为 AVL 树,它或者是一棵空树,或者是有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左右子树的深度之差的绝对值不超过1。二叉树的的平衡因子 BF 为:该结点的左子树的深度减去它的右子树的深度,则平衡二叉树的所有结点的平衡因子为只可能是:-1、0 和1一棵好的平衡二叉树的特征:(1)保证有 n 个结点的树的高度为 O(logn)(2)容易维护,也就是说,在做数据项的插入或删除操作时,为平衡树所做的一些辅助操作

2、时间开销为 O(1)一、平衡二叉树的构造在一棵二叉查找树中插入结点后,调整其为平衡二叉树。若向平衡二叉树中插入一个新结点后破坏了平衡二叉树的平衡性。首先要找出插入新结点后失去平衡的最小子树根结点的指针。然后再调整这个子树中有关结点之间的链接关系,使之成为新的平衡子树。当失去平衡的最小子树被调整为平衡子树后,原有其他所有不平衡子树无需调整,整个二叉排序树就又成为一棵平衡二叉树1.调整方法(1)插入点位置必须满足二叉查找树的性质,即任意一棵子树的左结点都小于根结点,右结点大于根结点(2)找出插入结点后不平衡的最小二叉树进行调整,如果是整个树不平衡,才进行整个树的调整。2.调整方式(1)LL 型LL

3、 型:插入位置为左子树的左结点,进行向右旋转(LL 表示的是在做子树的左结点进行插入)由于在 A 的左孩子 B 的左子树上插入结点 F,使 A 的平衡因子由1变为2,成为不平衡的最小二叉树根结点。此时 A 结点顺时针右旋转,旋转过程中遵循“旋转优先”的规则,A 结点替换 D 结点成为 B 结点的右子树,D 结点成为 A 结点的左孩子。(2)RR 型RR 型:插入位置为右子树的右孩子,进行向左旋转由于在 A 的右子树 C 的右子树插入了结点 F,A 的平衡因子由-1变为-2,成为不平衡的最小二叉树根结点。此时,A 结点逆时针左旋转,遵循 “旋转优先”的规则,A 结点替换 D 结点成为 C 的左子

4、树,D 结点成为 A 的右子树。(3)LR 型LR 型:插入位置为左子树的右孩子,要进行两次旋转,先左旋转,再右旋转;第一次最小不平衡子树的根结点先不动,调整插入结点所在的子树,调整后的树变成 LL 型树,第二次再调整最小不平衡子树(根据 LL 型的调整规则,调整为平衡二叉树) 。由于在 A 的左子树 B 的右子树上插入了结点 F,A 的平衡因子由1变为了2,成为不平衡的最小二叉树根结点。第一次旋转 A 结点不动,先将 B 的右子树的根结点 D 向左上旋转提升到 B 结点的位置,然后再把该 D 结点向右上旋转提升到 A 结点的位置。(4)RL 型RL 型:插入位置为右子树的左孩子,进行两次调整

5、,先右旋转调整为 RR 型,再左旋转,从 RR 型调整到平衡二叉树;处理情况与 LR 类似。总结:RR 型和 LL 型插入导致的树失去平衡,只需要做一次旋转调整即可。而 RL 型和LR 型插入导致的结点失去平衡,要调整两次。对于 RL/LR 的调整策略是:第一次调整,最小不平衡子树的根结点先不动,调整插入结点所在的子树(这个子树是指最小不平衡结点的一颗子树,且这棵子树是插入结点的子树)为 RR 型或者 LL 型,第二次再调整最小不平衡子树(调整策略要么是 RR 型要么是 LL 型)。#include#include#includeusing namespace std;#define LH 1

6、/左高#define EH 0/等高#define RH -1/右高struct TreeNodeint m_nValue;int BF;/平衡因子TreeNode *lchild;TreeNode *rchild;class AVLTreepublic:AVLTree();AVLTree();void CreateTree(TreeNode */创建 AVLvoid PreTraver(TreeNode *root);/先序遍历void RR_Rotate(TreeNode */右旋转处理int GetHeight(TreeNode *root);/获得树的高度int GetBF(TreeN

7、ode *root);/获得树的平衡因子void LL_Rotate(TreeNode */左旋转处理void RL_Rotate(TreeNode */双旋处理,先右旋转,再左旋转void LR_Rotate(TreeNode */双旋处理,先左旋转,再右旋转void LeftBalance(TreeNode */左平衡处理void RightBalance(TreeNode */右平衡处理;int Max(int a,int b)if(ab)return a;else return b;int AVLTree:GetHeight(TreeNode *root)int len;if(root

8、=NULL)len=0;elselen=Max(GetHeight(root-lchild),GetHeight(root-rchild)+1;return len;int AVLTree:GetBF(TreeNode *root)int bf;/平衡因子bf=GetHeight(root-lchild)-GetHeight(root-rchild);return bf;void AVLTree:CreateTree(TreeNode *root-m_nValue=data;root-lchild=NULL;root-rchild=NULL;/ root-BF=GetBF(root);root

9、-BF=EH;/初始叶子结点的平衡因子为等高else if(datam_nValue)CreateTree(root-lchild,data);switch(root-BF)/检查 root 的平衡度case LH:/原来树 root 的左子树比右子树高,现在左子树更高LeftBalance(root);/对树进行左平衡处理break;case EH:/原来树 root 的左右子树等高,现在左子树高root-BF=LH;/root 的平衡因子由0 变为1break;case RH:/原来树 root 的右子树比左子树高,现在左右子树等高root-BF=EH;else if(dataroot-m

10、_nValue) CreateTree(root-rchild,data);switch(root-BF)case LH:root-BF=EH;/原来树 root 的左子树比右子树高,现在 root 的左右子树等高break;case EH:/原来树 root 的左右子树等高,现在 root 的右子树更高root-BF=RH;break;case RH:/原来右子树比左子树高,现在 root 右子树高RightBalance(root);/对树 root 作右平衡处理void AVLTree:PreTraver(TreeNode *root)if(root) cout.width(3);cou

11、tm_nValue;if(root-lchild)PreTraver(root-lchild);if(root-rchild)PreTraver(root-rchild);void AVLTree:LL_Rotate(TreeNode *p=r-rchild;/p 指向 r 的右孩子结点r-rchild=p-lchild;/r 结点左旋转成为 p 的左子树,p 原来的左子树成为 r 的右子树p-lchild=r;/r 成为 p 的左孩子r=p;void AVLTree:RR_Rotate(TreeNode *p=r-lchild;r-lchild=p-rchild;p-rchild=r;r=p

12、;void AVLTree:RL_Rotate(TreeNode *p=r-rchild;RR_Rotate(p);/最小失衡树的根结点的右子树根结点进行右旋转r-rchild=p;/更新最小失衡树根结点的右孩子LL_Rotate(r);/最小失衡树的根结点进行左旋转void AVLTree:LR_Rotate(TreeNode *p=r-lchild;LL_Rotate(p);/最小失衡树根结点的左子树根结点进行左旋转r-lchild=p;/更新最小失衡树根结点的左孩子RR_Rotate(r);/最小失衡树根结点进行右旋转void AVLTree:LeftBalance(TreeNode *

13、lc=T-lchild;/lc 指向 T 的左孩子结点switch(lc-BF)/检查 T 左子树的平衡因子case LH:/新结点插入在 T 的左孩子的左子树上,导致左子树的平衡因子为左高,进行右旋转处理T-BF=lc-BF=EH;/旋转后,原根结点和左孩子结点平衡因子都 为0RR_Rotate(T);/右旋转处理break;case RH:/新结点插入在 T 的左孩子的右子树上,导致左子树的平衡因子为右高,进行LR 处理rd=lc-rchild;switch(rd-BF)case LH:/新结点插入在 T 的左孩子的右子树的左子树上T-BF=RH;/旋转后,原根结点的平衡因子为右高lc-B

14、F=EH;/旋转后,原根结点的左孩子结点平衡因子为等高break;case EH:/新结点插入到 T 的左孩子的右孩子(叶子)T-BF=lc-BF=EH;/旋转后,原根和左孩子结点的平衡因子都为等高break;case RH:/新结点插入在 T 的左孩子的右子树的右子树上T-BF=EH;/旋转后,原根结点的平衡因子为等高lc-BF=LH;/旋转后,原根结点的左孩子结点平衡因子为左高rd-BF=EH;/旋转后的新结点的平衡因子为等高/双旋转处理LL_Rotate(T-lchild);/对 T 的左子树左旋转处理RR_Rotate(T);/对 T 作右旋转处理 void AVLTree:Right

15、Balance(TreeNode *rc=T-rchild;switch(rc-BF)case RH:/新结点插入在 T 的右孩子的右子树上,导致右子平衡因子为右高,进行左旋转处理T-BF=rc-BF=EH;/旋转后,原根结点和右孩子结点的平衡因子均为0LL_Rotate(T);break;case LH:/新结点插入在 T 的右孩子的左子树上,导致右子树的平衡因子为左高,进行双旋处理ld=rc-lchild;switch(ld-BF)case RH:/新结点插入在 T 的右孩子的左子树的右子树上T-BF=LH;/旋转后,原根结点的平衡因子为左高rc-BF=EH;/旋转后,原根结点的右孩子结点

16、平衡因子为等高break;case EH:/新结点插入到 T 的右孩子的左孩子(叶子)T-BF=rc-BF=EH;/旋转后,原根和右孩子结点的平衡因子等高break;case LH:/新结点插入到 T 的右孩子的左子树的左子树T-BF=EH;/旋转后,原根结点的平衡因子等高rc-BF=RH;/旋转后,原根结点的右孩子结点的平衡因子为右高ld-BF=EH;/旋转后的新根结点的平衡因子为等高/双旋转处理RR_Rotate(T-rchild);/对 T 的右子树作右旋转处理LL_Rotate(T);/对 T 作左旋转处理 int main()const char *file=“data.txt“;AVLTree AVL=AVLTree();TreeNode *root=NULL;int data;ifstream fin;fin.open(file);if(fin.is_open()while(1)findata;if(data=-1)break;AVL.CreateTree(root,data); AVL.PreTraver(root);coutendlendl; fin.close();return 1;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医学治疗 > 基础医学

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报