介绍
AVL树是一个自平衡的二叉查找树,此树的任意左子树与右子树的高度差不会超过1。
如:下图一是一个AVL树,而图二不是AVL树。
为什么需要AVL树
BST树一些基本操作像insert,search,max,min最坏的情况下需要O(n),其中n是节点个数。我们如何保证在每次插入后,对树的一些基本操作在最坏情况下保持在O(logn)的范围。这时就需要一个新的树,我们本节介绍自平衡树AVL。
AVL 树的insert
为了保证AVL树在每次插入后,树的左右子树的高度差不会超过一,我们需要对树做一些旋转操作。旋转操作要保证BST树的基本特性:key(left) < key(root) < key(right)
AVL树插入的步骤:
比如我们要往一个AVL树中插入一个节点w:
- 执行基本的BST插入w
- 从w节点开始,向上遍历发现第一个非平衡的节点,比如是 z。我们令y为z的孩子节点,x为z的孙子节点。
- 重新平衡树在z的子节点上。这儿有可能有四种情况因为y,x,z的位置关系。
- y是z的左孩子,x是y的左孩子(右旋)
- y是z的左孩子,x是y的右孩子(先左旋后右旋)
y是z的右孩子,x是y的右孩子(左旋)
y是z的右孩子,x是y的左孩子(先右旋后左旋)
java 实现
构建avl树
public class AWL {
private static class Node {
private Node left;
private Node right;
private int val;
public Node(int val) {
this.val = val;
}
}
/**
* 节点树的插入
* @param node
* @param key
*/
private static Node insert (Node node ,int key) {
if (node == null) {
return new Node(key);
}
if (key == node.val) {
return node;
}
if (key < node.val) {
node.left = insert(node.left,key);
}
else if (key > node.val) {
node.right = insert(node.right,key);
}
/**
* 进行旋转操作
*/
int banance = getBanlance(node);
if (banance > 1) {
if (node.left != null && key < node.left.val) {
return roateRight(node);
}
else if (node.left != null && key > node.left.val) {
node.left = roateLeft(node.left);
return roateRight(node);
}
}
else if (banance < -1) {
if (node.right != null && key > node.right.val) {
return roateLeft(node);
}
else if (node.right != null && key < node.right.val) {
node.right = roateRight(node.right);
return roateLeft(node);
}
}
return node;
}
/**
* 计算树的高度
* @param node
* @return
*/
public static int height(Node node) {
if (node == null) {
return 0;
} else {
return Math.max(1 + height(node.left),1+height(node.right));
}
}
/**
* 计算树的平衡高度
* @param node
* @return
*/
public static int getBanlance(Node node) {
int leftHeight = height(node.left);
int rightHeight = height(node.right);
return leftHeight - rightHeight;
}
/**
* 左旋实现
* @param node
* @return
*/
private static Node roateLeft(Node node) {
Node root = node.right;
Node templeft = root.left;
node.right = templeft;
root.left = node;
return root;
}
/**
* 右旋实现
* @param node
* @return
*/
private static Node roateRight(Node node) {
Node root = node.left;
Node tempRight = root.right;
root.right = node;
node.left = tempRight;
return root;
}
/**
* 前序遍历
* @param root
*/
private static void preNode(Node root) {
if (root != null) {
System.out.print(root.val +" ");
preNode(root.left);
preNode(root.right);
}
}
/**
* 层序遍历
* @param args
*/
private static void levelNode(Node root) {
Queue<Node> queue = new LinkedList<AWL.Node>();
queue.add(root);
Node topNode = null;
while (!queue.isEmpty()) {
int size = queue.size();
int i = 0;
while (i < size) {
topNode = queue.poll();
System.out.print(topNode.val + " ");
if (topNode.left != null) {
queue.add(topNode.left);
}
if (topNode.right != null) {
queue.add(topNode.right);
}
i = i + 1;
}
System.out.println();
}
}
public static void main(String[] args) {
Node root = new Node(20);
root = insert(root,10);
root = insert(root,30);
root = insert(root,15);
root = insert(root,14);
root = insert(root,16);
levelNode(root);
}
}