平衡二叉树
一、概念
平衡二叉树是基于排序二叉树,当向排序二叉树顺序插入元素时,会导致二叉树退化为一个链表,查找元素的时间复杂降至O(n);二平衡二叉树在插入元素时会自动检测左右子树的高度差,当左右子树的高度差大与1时会自动进行平衡,从而实排序二叉树始终处于平衡,时间复杂度为O(lgN)
二、平衡策略
平衡二叉树存在四种失衡的情况,对应四种平衡策略。在进行平衡调整时,从新加入的节点向上查找,找到第一个失衡的树时,对该树的节点进行调整
1、右孩子的右子树
当右孩子的右子树导致失衡时,需要进行左旋转
2、左孩子的左子树
当左孩子的左子树导致失衡时,需要进行右旋转
3、右孩子的左子树
当右孩子的左子树导致失衡时,需要先进行右旋转,再进行左旋转
4、左孩子的右子树
当左孩子的右子树导致失衡时,需要先进行左旋转,再进行右旋转
左旋与右旋是针对失衡节点来说的
先右后左,右旋是针对失衡点右孩子来说的,左旋是针对失衡点来说的
先左后右,左旋是针对失衡点左孩子来说的,右旋是针对失衡点来说的
三、删除节点
1、叶子节点
叶子节点直接删除
2、只有一颗子树
删除后,将该节点替换为儿子节点
3、有两颗子树
删除后,将该节点左子树最大的节点替换为该节点;或将该节点右子树最大的节点替换为该节点
四、代码
1、创建节点
@Data
public class Node {
private int value;
private Node left;
private Node right;
public Node(int value) {
this.value = value;
}
public void add(Node node) {
if (node == null) {
return;
}
if (node.getValue() < this.getValue()) {
if (this.getLeft() == null) {
this.setLeft(node);
} else {
this.getLeft().add(node);
}
} else {
if (this.getRight() == null) {
this.setRight(node);
} else {
this.getRight().add(node);
}
}
// 旋转
if (rightHeight()-leftHeight()>1){
if (this.right.leftHeight()>this.right.rightHeight()){
// 先右后左
this.right.rightRotate();
leftRotate();
}else {
// 左旋
leftRotate();
}
}else if (leftHeight()-rightHeight()>1){
if (this.left.rightHeight()>this.left.leftHeight()){
// 先左后右
this.left.leftRotate();
rightHeight();
}else {
// 右旋
rightRotate();
}
}
}
// 左旋
public void leftRotate(){
Node node=new Node(this.value);
node.left=this.left;
node.right=this.right.left;
this.value=this.right.value;
this.right=this.right.right;
this.left=node;
}
// 右旋
public void rightRotate(){
Node node=new Node(this.value);
node.left=this.left.right;
node.right=this.right;
this.value=this.left.value;
this.left=this.left.left;
this.right=node;
}
// 中序遍历
public void infixOrder() {
if (this.getLeft() != null) {
this.getLeft().infixOrder();
}
System.out.println(this.getValue());
if (this.getRight() != null) {
this.getRight().infixOrder();
}
}
// 高度
public int height() {
return Math.max(this.getLeft() == null ? 0 : this.getLeft().height(), this.getRight() == null ? 0 : this.getRight().height()) + 1;
}
// 左子树高度
public int leftHeight() {
if (this.getLeft() == null) {
return 0;
} else {
return this.getLeft().height();
}
}
// 右子树高度
public int rightHeight() {
if (this.getRight() == null) {
return 0;
} else {
return this.getRight().height();
}
}
// 查询节点
public Node search(int value) {
if (this.value == value) {
return this;
}
if (value < this.value && this.left != null) {
return this.left.search(value);
} else if (value >= this.value && this.right != null) {
return this.right.search(value);
} else {
return null;
}
}
// 查询父节点
public Node searchParent(int value) {
if ((this.left != null && this.left.value == value) || (this.right != null && this.right.value == value)) {
return this;
} else if (value < this.value && this.left != null) {
return this.left.searchParent(value);
} else if (value >= this.value && this.right != null) {
return this.right.searchParent(value);
} else {
return null;
}
}
// 删除节点
public Node delNode(int value) {
Node target = search(value);
if (target != null) {
Node parent = searchParent(value);
// 叶子节点
if (target.left == null && target.right == null) {
if (parent.left != null && parent.left.getValue() == value) {
parent.left = null;
} else if (parent.right != null && parent.right.getValue() == value) {
parent.right = null;
}
// 只有一颗左子树
} else if (target.left!=null && target.right==null){
if (parent!=null) {
if (parent.left != null && parent.left.getValue() == value) {
parent.left = target.getLeft();
} else if (parent.right != null && parent.right.getValue() == value) {
parent.right = target.getLeft();
}
}else {
target.value=target.left.value;
target.left=null;
}
}else if (target.left==null){
if (parent!=null) {
if (parent.left != null && parent.left.getValue() == value) {
parent.left = target.getRight();
} else if (parent.right != null && parent.right.getValue() == value) {
parent.right = target.getRight();
}
}else {
target.value=target.right.value;
target.right=null;
}
}else {
// 两颗子树
Node largNode = queryNewRoot(target.getRight());
Node temp=target;
target.value=largNode.value;
return temp;
}
return target;
} else {
return null;
}
}
// 查询右子树
public Node queryNewRoot(Node node){
if (node.left==null){
Node parent = searchParent(node.value);
if (parent.left.value==node.value){
parent.left=null;
}else {
parent.right=null;
}
return node;
}else {
return queryNewRoot(node.left);
}
}
}
2、创建平衡二叉树
@Data
public class SortTree {
private Node root;
// 添加节点
public void add(Node node) {
if (root == null) {
root = node;
} else {
root.add(node);
}
}
public void infixOrder() {
if (root != null) {
root.infixOrder();
} else {
System.out.println("该树为空树,无法遍历");
}
}
public int height() {
return root.height();
}
public int leftHeight() {
if (root == null || root.getLeft() == null) {
return 0;
} else {
return root.leftHeight();
}
}
public int rightHeight() {
if (root == null || root.getRight() == null) {
return 0;
} else {
return root.rightHeight();
}
}
public Node search(int value) {
if (root == null) {
return null;
} else {
return root.search(value);
}
}
public Node searchParent(int value) {
if (root == null) {
return null;
} else {
return root.searchParent(value);
}
}
public Node delNode(int value){
if (root==null){
return null;
}else if (root.height()==1 && root.getValue()==value){
root=null;
return root;
}else{
return root.delNode(value);
}
}
}