数据结构之平衡二叉树的平衡因子BF 的计算

在书上看了平衡二叉树的代码后,发现前人的智慧真是无限。但是因为一次性给出的最完美的代码让人有时候看不太懂...

后来经过仔细推敲,才慢慢发现了其中的奥秘。一开始并不知道关于平衡二叉树的平衡因子BF是怎么修改的,后来才发现关于平衡二叉树的最重要的一句话:在构建平衡二叉树的过程中,每当插入一个结点时,先检查是否因插入而破坏了树的平衡性,若是,则找出最小不平衡子树,在保持二叉排序树特性的前提下,调整关系。

这句话意味着:只要破坏了平衡性,就马上修改使得二叉树重新平衡,意思就是只要修改了最小不平衡树就可以使得整个二叉树重新平衡.

下面借用书上的代码进行解释说明,说明在代码后面

[cpp] view plaincopy

	1. #include "stdio.h"      
	2. #include "stdlib.h"     
	3. #include "io.h"    
	4. #include "math.h"    
	5. #include "time.h"  
	6.   
	7. #define OK 1  
	8. #define ERROR 0  
	9. #define TRUE 1  
	10. #define FALSE 0  
	11. #define MAXSIZE 100 /* 存储空间初始分配量 */  
	12.   
	13. typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */   
	14.   
	15.   
	16. /* 二叉树的二叉链表结点结构定义 */  
	17. typedef  struct BiTNode /* 结点结构 */  
	18. {  
	19.     int data;   /* 结点数据 */  
	20.     int bf; /*  结点的平衡因子 */   
	21.     struct BiTNode *lchild, *rchild;    /* 左右孩子指针 */  
	22. } BiTNode, *BiTree;  
	23.   
	24.   
	25. /* 对以p为根的二叉排序树作右旋处理, */  
	26. /* 处理之后p指向新的树根结点,即旋转处理之前的左子树的根结点 */  
	27. void R_Rotate(BiTree *P)  
	28. {   
	29.     BiTree L;  
	30.     L=(*P)->lchild; /*  L指向P的左子树根结点 */   
	31.     (*P)->lchild=L->rchild; /*  L的右子树挂接为P的左子树 */   
	32.     L->rchild=(*P);  
	33.     *P=L; /*  P指向新的根结点 */   
	34. }  
	35.   
	36. /* 对以P为根的二叉排序树作左旋处理, */  
	37. /* 处理之后P指向新的树根结点,即旋转处理之前的右子树的根结点0  */  
	38. void L_Rotate(BiTree *P)  
	39. {   
	40.     BiTree R;  
	41.     R=(*P)->rchild; /*  R指向P的右子树根结点 */   
	42.     (*P)->rchild=R->lchild; /* R的左子树挂接为P的右子树 */   
	43.     R->lchild=(*P);  
	44.     *P=R; /*  P指向新的根结点 */   
	45. }  
	46.   
	47. #define LH +1 /*  左高 */   
	48. #define EH 0  /*  等高 */   
	49. #define RH -1 /*  右高 */   
	50.   
	51. /*  对以指针T所指结点为根的二叉树作左平衡旋转处理 */  
	52. /*  本算法结束时,指针T指
  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
平衡二叉树是一种特殊的二叉搜索树,它的左右子树的高度差不超过1,这样可以保证平衡二叉树的查找、插入和删除操作的时间复杂度都是O(log n)。 平衡二叉树有很多种,其中比较常见的有AVL树、红黑树、B树等。在本文中,我们主要介绍AVL树。 AVL树是一种严格平衡的二叉搜索树,它的每个节点的左右子树高度差不超过1。当节点的高度差超过1时,就需要通过旋转操作来重新平衡。AVL树的特点是:对于一个节点,其左右子树的高度差不超过1,且左右子树都是AVL树。 插入操作 插入操作是AVL树中比较复杂的操作,因为插入一个节点可能导致整个树失去平衡。下面是AVL树的插入操作: 1. 在AVL树中插入一个节点,首先按照二叉搜索树的规则找到插入的位置。 2. 如果插入节点后,其父节点的左右子树高度差不超过1,则不需要进行旋转操作,直接返回。 3. 如果插入节点后,其父节点的左右子树高度差超过1,则需要进行旋转操作。 4. 如果插入节点在父节点的左子树中,并且插入节点的左子树高度大于插入节点的右子树高度,则进行右旋操作;如果插入节点在父节点的右子树中,并且插入节点的右子树高度大于插入节点的左子树高度,则进行左旋操作。 5. 如果插入节点在父节点的左子树中,并且插入节点的左子树高度小于插入节点的右子树高度,则进行左右旋转操作;如果插入节点在父节点的右子树中,并且插入节点的右子树高度小于插入节点的左子树高度,则进行右左旋转操作。 删除操作 删除操作也是AVL树中比较复杂的操作,因为删除一个节点可能导致整个树失去平衡。下面是AVL树的删除操作: 1. 在AVL树中删除一个节点,首先按照二叉搜索树的规则找到要删除的节点。 2. 如果要删除的节点没有子节点,则直接删除即可。 3. 如果要删除的节点只有一个子节点,则将子节点替换成要删除的节点。 4. 如果要删除的节点有两个子节点,则先找到要删除节点的后继节点(即右子树中最小的节点),将后继节点的值赋给要删除的节点,然后将后继节点删除。 5. 删除一个节点可能会导致整个树失去平衡,因此需要进行旋转操作。 6. 如果删除节点后,其父节点的左右子树高度差不超过1,则不需要进行旋转操作,直接返回。 7. 如果删除节点后,其父节点的左右子树高度差超过1,则需要进行旋转操作。 8. 如果删除节点在父节点的左子树中,并且删除节点的左子树高度大于删除节点的右子树高度,则进行右旋操作;如果删除节点在父节点的右子树中,并且删除节点的右子树高度大于删除节点的左子树高度,则进行左旋操作。 9. 如果删除节点在父节点的左子树中,并且删除节点的左子树高度小于删除节点的右子树高度,则进行左右旋转操作;如果删除节点在父节点的右子树中,并且删除节点的右子树高度小于删除节点的左子树高度,则进行右左旋转操作。 总结 AVL树是一种严格平衡的二叉搜索树,它的每个节点的左右子树高度差不超过1。插入和删除操作可能会导致整个树失去平衡,需要通过旋转操作来重新平衡。AVL树比较适合用于读取操作比较频繁的场景,因为它的查找、插入和删除操作的时间复杂度都是O(log n)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值