平衡二叉树
AVL树
BST存在的问题:如果给数列 {1,2,3,4,5,6} 构建二叉树,左子树全部为空,从形式上看,更像是一个单链表,插入速度没有影响,查询速度明显降低。
解决方案:平衡二叉树
- 平衡二叉树也称为平衡二叉搜索树(self-balancing binary search tree),又被称为 AVL 树,可以保证查询效率较高
- 特点:它是一颗空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一颗平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。
左旋转
处理不满足平衡二叉树条件(高度差小于一)的二叉树 – 进行左旋转(右子树高度高于左子树)
-
创建一个新的节点 newNode (以root的值进行创建),创建一个新的节点,值等于当前根节点的的值
-
把新节点的左子树设置了当前节点的左子树
newNode.left = left
-
把新节点的右子树设置为当前节点的右子树的左子树
newNode.right = right.left
-
把当前节点的值换为右子节点的值
Value = right.value
-
把当前节点的右子树设置为右子树的右子树
right = right.rigth
-
把当前节点的左子树设置为新节点
left = newNode
// class Node
// 添加计算左右树高度、高度的方法
// 左旋转的方法
// add方法中加入判断是否进行左旋转的条件
class Node{
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
// return height of left tree
public int leftHeight(){
if(left==null){
return 0;
}
return left.height();
}
// return height of right height
public int rightHeight(){
if(right==null){
return 0;
}
return right.height();
}
// return the height of the tree with this current node as the root node
public int height(){
return Math.max(left==null ? 0:left.height(),right == null?0:right.height())+1;
}
// rotate left
private void leftRotate(){
// create new node with value of current node
Node newNode = new Node(value);
// set left tree of new node to left tree of current node
newNode.left = left;
// set left tree of new node to left tree of right tree of current node
newNode.right = right.left;
// set value of current node to the value of right sub node
value = right.value;
// set right tree of current node to right tree of right tree of current node
right = right.right;
// set left tree(node) of current node to new node
left = newNode;
}
// find node wait for deleting
/**
*
* @param value The value of node you wish to delete
* @return if find it, return this node, or return null
*/
public Node search(int value){
if(value==this.value){ // find it
return this;
} else if(value<this.value){
// if value smaller than current node, find it recursively to left side
// if left node is null, return null
if(this.left==null){
return null;
}
return this.left.search(value);
} else{
// recursively search to right side
if(this.right==null){
return null;
}
return this.right.search(value);
}
}
// find the parent node of the node to be deleted
/**
*
* @param value the value of node you want to find
* @return the parent node of the node to be deleted, if not found, 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 is smaller than current value and left node of current node is not null
// recursively find left side
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;
}
}
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
// add Node recursively
public void add(Node node ){
if(node == null){
return;
}
// determine the relationship of node's value and
// the value of the root node of the current subtree
if(node.value<this.value){
if(this.left==null){
this.left = node;
}else{ // 如果当前节点的左子树不为空,则向左递归添加node
this.left.add(node);
}
} else{ // 添加的节点的值大于当前节点的值
if(this.right==null){
this.right = node;
} else{
this.right.add(node);
}
}
// after add a node, if (height of right tree - height of left tree)>1
// rotate left
if(rightHeight()-leftHeight()>1){
if(rightHeight()-leftHeight()>1){
// if(right!=null && right.rightHeight()<right.leftHeight()){
// rotate right tree first
leftRotate(); // left rotate
}
}
}
// infix order traversal
public void infixOrder(){
if(this.left!=null){
this.left.infixOrder();
}
System.out.print(this.value+" ");
if(this.right!=null){
this.right.infixOrder();
}
}
}
// class AVLTree
class AVLTree{
private Node root;
// find node to be deleted
public Node search(int value){
if(root==null){
return null;
} else{
return root.search(value);
}
}
// find parent node
public Node searchParent(int value){
if(root==null){
return null;
} else{
return root.searchParent(value);
}
}
// 1. return the min value of BST with node as the root
// 2. delete the smallest node of BST with node as the root
/**
*
* @param node Incoming node ( as root node of BST)
* @return the min value of BST with node as the root
*/
public int delRightTreeMin(Node node){
Node target = node;
// cyclic search left node to find the minimum node
while(target.left!=null){
target = target.left;
}
// now target is the minimum value
delete(target.value);
return target.value;
}
// delete node
public void delete(int value){
if (root==null){
return;
} else{
// 1. find targetNode (node to be deleted)
Node targetNode = search(value);
if(targetNode==null){
return;
}
// if this tree only have one node
if(root.left==null && root.right==null){
root = null;
return;
}
// find parent node of targetNode
Node parent = searchParent(value);
// if node to be deleted is leaf node
if(targetNode.left == null && targetNode.right == null){
// determine target node is right or left node of parent node
if(parent.left!=null && parent.left.value == value){
parent.left = null;
} else if(parent.right != null && parent.right.value == value){
parent.right = null;
}
} else if(targetNode.left != null && targetNode.right != null){
// delete node who has two subtrees
// find the min value of right tree
int min = delRightTreeMin(targetNode.right);
targetNode.value = min;
} else{ // delete node only with one subtree
// if node to be deleted has left node
if(targetNode.left!=null){
if (parent!=null){
// if targetNode is left node of parent node
if(parent.left.value == value){
parent.left = targetNode.left;
} else{ // target node is right node of parent node
parent.right = targetNode.left;
}
}else{
root = targetNode.left;
}
} else{ // node to be deleted has right node
// if target node is left node of parent node
if(parent!=null){
if(parent.left.value == value){
parent.left = targetNode.right;
} else{
parent.right = targetNode.right;
}
} else{
root = targetNode.right;
}
}
}
}
}
// add
public void add(Node node){
if(root==null){
root = node;
} else{
root.add(node);
}
}
public Node getRoot() {
return root;
}
// traversal
public void infixOrder(){
if(root!=null){
root.infixOrder();
} else{
System.out.println("can not traverse");
}
}
}
// main
public class AVLTreeDemo {
public static void main(String[] args) {
int[] arr = {4,3,6,5,7,8};
AVLTree avlTree = new AVLTree();
for (int i = 0; i < arr.length; i++) {
avlTree.add(new Node(arr[i]));
}
// traversal
System.out.println("infix order: ");
avlTree.infixOrder();
System.out.println("\n"+avlTree.getRoot().height()); // 4 - 3
System.out.println("\n"+avlTree.getRoot().leftHeight()); // 1 - 2
System.out.println("\n"+avlTree.getRoot().rightHeight()); // 3 - 2
}
}
右旋转
左子树的高度高于右子树的高度,进行右旋转
-
创建一个新的节点 newNode (以root的值进行创建),创建一个新的节点,值等于当前根节点的的值
-
把新节点的右子树设置了当前节点的右子树
newNode.right = right
-
把新节点的左子树设置为当前节点的左子树的右子树
newNode.left = left.right
-
把当前节点的值换为左子节点的值
value = left.value
-
把当前节点的左子树设置为左子树的左子树
left = left.left
-
把当前节点的右子树设置为新节点
right = newNode
//class Node
// right rotate
private void rightRotate(){
Node newNode = new Node(value);
newNode.right = right;
newNode.left = left.right;
value = left.value;
left = left.left;
right = newNode;
}
双旋转
问题分析:
- 当符合右旋转的条件时
- 如果它的左子树的右子树的高度大于它的左子树的高度
- 先对当前这个节点的左节点进行左旋转
- 再对当前节点进行右旋转的操作
// after add a node, if (height of right tree - height of left tree)>1
// rotate left
if(rightHeight()-leftHeight()>1){
if(right!=null && right.rightHeight()<right.leftHeight()){
right.rightRotate();
// rotate right tree of current node first, then left rotate
leftRotate(); // left rotate
}else{
leftRotate();
}
return; // must have!!! or code will going
}
if(leftHeight()-rightHeight()>1){
// if right tree of its left tree is higher than its left tree
if(left!=null && left.rightHeight()>left.leftHeight()){
// left rotate left tree of current node
left.leftRotate();
// right rotate current node
rightRotate();
} else {
rightRotate();
}
}