平衡二叉排序树
2015-06-21 21:49
447 查看
因为二叉树本身就是个递归的概念,所以在构建平衡二叉树的时候,应时刻记得递归这个概念。
同样的序列,因为排序不同,可能会生成不同的二叉排序树,查找效率性对就不一定了,如:1-9这些数字就可以生成下面两种树。
第二种就是一个极端的情况,如果要查找9,就需要进行比较8次,效率很低。由此就引出,平衡二叉树的概念。
什么是平衡二叉树?
希望对一个序列,进行查找,最好的就是将其构建成一个平衡二叉树即AVL树。
但是怎么构建平衡二叉排序树?
前提:必须是一棵树。(类似于:只有先保证他是一个人,才难说他是一个什么样的男人。嘻嘻,这个比喻不是那么准确啦)
下面有一个题目:
怎么将左图构建成右图的平衡二叉树呢?
可见,左图和右图的不同就在于是否是平衡的。左图中节点9的平衡因子是2,是个不平衡点。
构造平衡二叉树:
如果在一棵平衡的二叉搜索树中,插入一个新节点时,造成了不平衡。此时必须调整树的结构,使之平衡化。
平衡旋转有两类:
--单旋转(左旋和右旋)
--双旋转(左右旋和右左旋)
每插入一个新节点时,AVL树中相关节点的平衡状态会发生改变。因此,在插入一个新节点后,需要从插入位置沿着通向根的路径回溯,检查各节点的平衡因子。如果在某一节点发现此树不平衡,停止回溯。
从发生不平衡的节点起,沿着刚才回溯的路径取直接下两层的节点。
(1)如果这三个节点处在一条直线上,则采用单旋转进行平衡化。单旋转可按方向分为左单旋转和右单旋转。
(2)如果这三个节点处在一条折线上,则采用双旋转进行平衡化。单旋转可按方向分为先左后右旋转和先右后左旋转。
下面举两个简单的例子,便于理解。
1:a[10]={3,2,1,4,5,6,7,10,9,8};对于这压样一个一维数组,构建二叉平衡树。
此时构建过程已经完成。
例子2:
下面是代码实现:
同样的序列,因为排序不同,可能会生成不同的二叉排序树,查找效率性对就不一定了,如:1-9这些数字就可以生成下面两种树。
第二种就是一个极端的情况,如果要查找9,就需要进行比较8次,效率很低。由此就引出,平衡二叉树的概念。
什么是平衡二叉树?
希望对一个序列,进行查找,最好的就是将其构建成一个平衡二叉树即AVL树。
但是怎么构建平衡二叉排序树?
前提:必须是一棵树。(类似于:只有先保证他是一个人,才难说他是一个什么样的男人。嘻嘻,这个比喻不是那么准确啦)
下面有一个题目:
怎么将左图构建成右图的平衡二叉树呢?
可见,左图和右图的不同就在于是否是平衡的。左图中节点9的平衡因子是2,是个不平衡点。
构造平衡二叉树:
如果在一棵平衡的二叉搜索树中,插入一个新节点时,造成了不平衡。此时必须调整树的结构,使之平衡化。
平衡旋转有两类:
--单旋转(左旋和右旋)
--双旋转(左右旋和右左旋)
每插入一个新节点时,AVL树中相关节点的平衡状态会发生改变。因此,在插入一个新节点后,需要从插入位置沿着通向根的路径回溯,检查各节点的平衡因子。如果在某一节点发现此树不平衡,停止回溯。
从发生不平衡的节点起,沿着刚才回溯的路径取直接下两层的节点。
(1)如果这三个节点处在一条直线上,则采用单旋转进行平衡化。单旋转可按方向分为左单旋转和右单旋转。
(2)如果这三个节点处在一条折线上,则采用双旋转进行平衡化。单旋转可按方向分为先左后右旋转和先右后左旋转。
下面举两个简单的例子,便于理解。
1:a[10]={3,2,1,4,5,6,7,10,9,8};对于这压样一个一维数组,构建二叉平衡树。
此时构建过程已经完成。
例子2:
下面是代码实现:
/*平衡二叉树的实现原理 时间:2015-6-21 ***/ #define LH 1//左子树高 #define EH 1//左右子树登高 #define RH 1//右子树 typedef struct BITNode{ int data; int bf; struct BITNode*lchild,*rchild; }BITNode,*BiTree; //右旋操作 void R_Rotate(BiTree *p) { BiTree L; L=(*p)->lchild; (*p)->lchild=L->rchild; L->rchild=(*p); *p=L; } //左旋操作 void L_Rotate(BiTree *p) { BiTree L; L=(*p)->rchild; (*p)->rchild=L->lchild; L->lchild=(*p); *p=L; } //左平衡 void LeftBalance(BiTree *T) { BiTree L,lr; L=(*T)->lchild; switch(L-bf) { case LH; (*T)->bf=L-bf=EH; R_RETATE(T) break; case RH; lr=L->rchild; switch(Lr-bf) { case LH; (*T)->bf=RH; L->bf=EH; break; case EH; (*T)->bf=L-bf=EH; break; case RH; (*T)->bf=EH; L-bf=LH; break; } lR->bf=EH; L_Rotate(&(*T)->lchild); R_Rotate(T); } } int InsertAVL(BITree *T,int n,int *taller)//taller用于判断插入节点后,树长高了没有 { if(!*T) { *T=(BiTree)malloc(sizeod(BITNode)); (*T)->data=e; (*T)->lchild=(*T)->rchild=NULL; (*T)->bf=EH; *taller=TRUE; } else{ if(e==(*T)->data) { *taller=FALSE; return FALSE; } if(e<(*T)->data) { if(!InsertAVL(&(*T))->lchild,e,taller) { return FALSE; } if(*taller)//判断树的长势 { switch((*T)->bf) { case LH: LeftBalance(T); *taller=FALSE; break; case EH: (*T)->bf=EH; *taller=TRUE; break; case RH: (*T)->bf=EH; *taller=FALSE; } } } else { if(!InsertAVL(&(*T))->rchild,e,taller) { return FALSE; } if(*taller)//判断树的长势 { switch((*T)->bf) { case LH: (*T)->bf=EH; *taller=FALSE; break; case EH: (*T)->bf=EH; *taller=TRUE; break; case RH: RightBalance(T); (*T)->bf=EH; *taller=FALSE; } } } } }
相关文章推荐
- 测试及调试
- 个人作业读后感
- 软件&工具
- Permission denied 与 553 Permission denied 错误解决方法
- 为python添加tab自动补全功能
- provider模式
- 个人 读后感
- 运行及总结
- 如何进行nginx或tomcat的性能调优(优秀推荐)
- JFreeChart—输出折线图
- Android:使用Socket网络通信时异常:java.net.SocketException: socket closed
- 2980 买帽子
- maven2中profile的介绍与使用
- Zabbix的集中式监控
- Devexpress中Tdxnavbar的使用
- 1的数目问题
- linux命令行中命令
- 网络配置命令
- eclipse配置python开发插件
- Github学习