目录
一、平衡二叉树
1.1 平衡二叉树简介
- 空树或它的左右两棵子树的高度差的绝对值不超过1,并且左右两棵子树都是平衡二叉树。
- 查询效率较高。
1.2 平衡二叉树示例
二、二叉排序树的左旋转
2.1 什么时候需要左旋转
- 当二叉排序树的右子树的高度(Rh)比左子树的高度(Lh)多1时,即Rh-Lh > 1。
2.2 左旋转思路
- 创建新的结点,赋值为当前结点(当前结点是指待处理子树的根结点)
- 将新结点的左子树设置为当前结点的左子树
- 将新的结点的右子树设置为当前结点的右子树的左子树
- 把当前结点的值替换为右子结点的值
- 把当前结点的右子树设置为右子树的右子树
- 把当前结点的左子树设置成刚刚创建的新结点
2.3 左旋转图解
2.4 左旋转代码实现
/**
* 该方法实现左旋转
*/
public void leftRotate() {
//创建新的结点,赋值为当前结点
Node newNode = new Node(value);
//将新结点的左子树设置成当前结点的左子树
newNode.left = left;
//将新的结点的右子树设置成当前结点的右子树的左子树
newNode.right = right.left;
//把当前结点的值替换为右子结点的值
value = right.value;
//把当前结点的右子树设置成右子树的右子树
right = right.right;
//把当前结点的左子树设置成新结点
left = newNode;
}
三、二叉排序树的右旋转
3.1 什么时候需要右旋转
- 当二叉排序树的左子树的高度(Lh)比右子树的高度(Rh)多1时,即Lh-Rh > 1。
3.2 右旋转思路
- 创建新的结点,赋值为当前结点(当前结点是指待处理子树的根结点)
- 将新结点的左子树设置为当前结点的左子树的右子树
- 将新的结点的右子树设置为当前结点的右子树
- 把当前结点的值替换为左子结点的值
- 把当前结点的左子树设置为左子树的左子树
- 把当前结点的右子树设置成刚刚创建的新结点
3.3 右旋转图解
3.4 右旋转代码
/**
* 该方法实现右旋转
*/
public void rightRotate() {
Node newNode = new Node(value);
newNode.right = right;
newNode.left = left.right;
value = left.value;
left = left.left;
right = newNode;
}
四、二叉排序树的双旋转
4.1 双旋转条件及图解
- 当符合右旋转条件时,若当前结点的左子树的右子树高度大于当前结点的左子树的左子树高度时,先对当前结点的左结点进行左旋转,再对当前结点右旋转。
- 当符合左旋转条件时,若当前结点的右子树的左子树高度大于当前结点的右子树的右子树高度时,先对当前结点的右结点进行右旋转,再对当前结点左旋转。这种情况下的图解与上面的类似,不再给出。
4.2 双旋转代码
// 每添加一次结点,判断左子树和右子树的高度
if (rightHeight() - leftHeight() > 1) {
// 若当前结点的右子树的左子树的高度大于当前结点的右子树的右子树的高度
if (right != null && right.leftHeight() > right.rightHeight()) {
// 对右子树右旋转
right.rightRotate();
}
leftRotate();
return;// 这句很重要
}
if (leftHeight() - rightHeight() > 1) {
// 若当前结点左子树的右子树的高度大于当前结点左子树的左子树高度
if (left != null && left.rightHeight() > left.leftHeight()) {
// 将当前结点的左结点左旋转
left.leftRotate();
}
// 再对当前结点进行右旋转
rightRotate();
}