重要参考:平衡二叉树(解惑)
平衡二叉树的java实现
平衡二叉树建立
static class Node{
Node parent;
Node leftChild;
Node rightChild;
int val;
public Node(Node parent, Node leftChild, Node rightChild,int val) {
super();
this.parent = parent;
this.leftChild = leftChild;
this.rightChild = rightChild;
this.val = val;
}
public Node(int val){
this(null,null,null,val);
}
public Node(Node node,int val){
this(node,null,null,val);
}
}
调整平衡二叉树
平衡二叉树AVL(平衡二叉树是一种特殊的二叉搜索树)失衡,分为左左(指在一个节点的左孩子的左孩子上插入节点(无论插得是左还是右节点)使二叉树失衡,就叫左左)、右右、左右、右左
调整平衡二叉树,可以通过“旋转”,但是首先必须明白一个核心操作,不让它叫“旋转”!而叫——>“两个结点的变换”
-
左左(右右)
- 只需一次变换,交换第一个不平衡的结点与它左(右)孩子的节点,若左(右)孩子有子节点,根据大小情况调整

- 只需一次变换,交换第一个不平衡的结点与它左(右)孩子的节点,若左(右)孩子有子节点,根据大小情况调整
-
左右
- 稍微复杂了点,需要进行两次交换,才能达到平衡,先交换第一个不平衡节点的左孩子和这个左孩子的右孩子节点,然后交换 交换后的第一个不平衡节点和它的左孩子

- 稍微复杂了点,需要进行两次交换,才能达到平衡,先交换第一个不平衡节点的左孩子和这个左孩子的右孩子节点,然后交换 交换后的第一个不平衡节点和它的左孩子
-
右左
- 先交换第一个不平衡节点的右孩子和这个右孩子的左孩子节点,然后交换 交换后的第一个不平衡节点和它的右孩子

- 一定要注意这个交换操作,比如a与b交换(a在上,b在下),b一定要占据a的位置!什么意思?就是b要放在(覆盖)储存a的那块内存上,
如何找到最小不平衡子树的根结点x,并判断出它是属于那种情况的?
-
插入一个结点时,我们首先找到需要插入的位置,并插入;数据结构上用的是递归
-
显然插入之后就要检查是否出现不平衡的结点
-
那么如何检查?
我们知道,你插入的时候用的是递归,一条线找到要插的位置,并插入;那么谁的平衡因子的有可能变呢? 不难想象,只有该条线上的结点的平衡因子有可能改变!那么我们在回溯的时候不就可以找到第一个不平衡的子树的结点?! -
可是我们如何判断该结点的平衡因子是否改变
显然要看它被插入结点的一边的深度是否增加; -
如何看它被插入结点的一边的深度是否增加?

如上图,如何看x的右孩子a(即被插入结点的一边)的深度增加?我们知道在a的右孩子上插入了结点y那么a的bf是一定要减1。那么x结点的bf?可根据a的bf决定是否改变!若a:bf变为-1或1,那么a之前一定为0,表示a的深度增加了,那么x的bf可根据a是x哪一边的孩子决定+1或-1;
若a:bf变为0,那么a之前一定为-1或1,表示a的深度每增加,那么不仅x的bf就不用变,该条线上的所有结点的bf都不用变,直接返回即可;
-
找到最小不平衡子树的根结点x了,如何判断它属于哪种不平衡呢?
没看懂,不过我觉得应该可以定义一个函数,专门用来判断属于哪种不平衡,在做插入删除操作后进行判断
删除节点(与二叉排序树删除方法相同,就是加入了平衡调整)
如果左右子树都非空。在高度较大的子树中实施删除操作。
- p为叶子节点,直接删除
- p只有一个子节点,将p删除掉后,将p的子节点代替p的位置
- p既有左子树也有右子树
- 先沿着p的左(右)子树的右(左)子节点一直往右(左)走,直到来到其右(左)子树的最右(左)边的一个节点r,然后将p中的关键字用r中的关键字代替,最后判断r是否为叶子节点,然后用上面两个方法处理
本文详细介绍了平衡二叉树(如AVL树)的建立过程、如何找到并调整最小不平衡子树,包括左左、右右、左右、右左四种失衡情况的处理方法。此外,还讨论了在插入和删除节点时如何维护平衡,并提供了一种判断不平衡状态的思路。

2888

被折叠的 条评论
为什么被折叠?



