对平衡二叉树的研究,大概已有半年之久。最近才算是对它有所领悟。因为网上好多博文对其讲解的都很好,在此就不再详述,只对其进行分篇章总结。
一、左旋转
在网上找到一左转GIF示意图。我借用一下:
在不平衡子树的右子树的右孩子插入结点导致的不平衡应该进行左旋转。
/**
* 约定null节点的高度为-1, 叶子结点高度为0。到根结点变大;
* @param node 某一节点引用;
* @return
*/
private int _height(AVLNode<T> node) {
return node == null ? -1 : node.height;
}
/**
* 逆时针单旋转;
* @param parent
* @return
*/
private AVLNode<T> _leftRotation(AVLNode<T> w) {
AVLNode<T> x = w.rChild;
w.rChild = x.lChild;
x.lChild = w;
w.height = Math.max(_height(w.lChild), _height(w.rChild)) + 1;
x.height = Math.max(w.height, _height(x.rChild)) + 1;
return x;
}
二、右旋转
右旋转与左旋转是镜像的如下:
在不平衡子树的左子树的左孩子插入结点导致的不平衡应该进行右旋转。
private AVLNode<T> _rightRotation(AVLNode<T> x) {
AVLNode<T> w = x.lChild;
x.lChild = w.rChild;
w.rChild = x;
x.height = Math.max(_height(x.lChild), _height(x.rChild)) + 1;
w.height = Math.max(x.height, _height(w.lChild)) + 1;
return w;
}
三、左右旋转
假如在不平子树根节点的左子树的右子树插入结点导致的不平衡。则先对根结点左子树旋转,再右转不平衡子树。
// lr
private AVLNode<T> _left_right_ratation(AVLNode<T> p) {
p.lChild = _leftRotation(p.lChild);
return _rightRotation(p);
}
四、右左旋转
假如在不平衡子树根节点的右子树的左子树插入结点导致的不平衡。则先对根节点的右子树旋转,再对不平衡子树根结点旋转。
private AVLNode<T> _right_left_ratation(AVLNode<T> p) {
p.rChild = _rightRotation(p.rChild);
return _leftRotation(p);
}
五、插入元素
插入后要沿着递归插入的路径回溯(出栈), 利用此性质对结点的平衡因子检查。如需旋转根据情况旋转,并刷新其高度。
private AVLNode<T> _insert(AVLNode<T> parent, T data) {
if (parent == null) {
parent = new AVLNode<T>(data);
}
int result = data.compareTo(parent.data);
if (result < 0) {
parent.lChild = _insert(parent.lChild, data);
if (_height(parent.lChild) - _height(parent.rChild) == 2) {
if (data.compareTo(parent.lChild.data) < 0) {
parent = _rightRotation(parent);
} else {
parent = _left_right_ratation(parent);
}
}
} else if (result > 0) {
parent.rChild = _insert(parent.rChild, data);
if (_height(parent.rChild) - _height(parent.lChild) == 2) {
if (data.compareTo(parent.rChild.data) > 0) {
parent = _leftRotation(parent);
} else {
parent = _right_left_ratation(parent);
}
}
} else {
// do nothing;
}
parent.height = Math.max(_height(parent.lChild), _height(parent.rChild)) + 1;
return parent;
}
完整代码:
public class AVLNode<T extends Comparable> {
public T data;
public int height;
public AVLNode<T> lChild;
public AVLNode<T> rChild;
public AVLNode(T data, int height ,AVLNode<T> lChild, AVLNode<T> rChild) {
this.data = data;
this.height = height;
this.lChild = lChild;
this.rChild = rChild;
}
// 委托构造;
public AVLNode(T data, AVLNode<T> lChild, AVLNode<T> rChild) {
this(data, 0, lChild, rChild);
}
// 委托构造;
public AVLNode(T data) {
this(data, null, null);
}
}
public class AVLDTree<T extends Comparable> implements Tree<T> {
private AVLNode<T> root;
@Override
public int height() {
return _height(root);
}
@Override
public void insert(T value) {
if (value == null) {
throw new RuntimeException("data null");
}
this.root = _insert(root, value);
}
/**
* 约定null节点的高度为-1, 叶子结点高度为0。到根结点变大;
* @param node 某一节点引用;
* @return
*/
private int _height(AVLNode<T> node) {
return node == null ? -1 : node.height;
}
/**
* 逆时针单旋转;
* @param parent
* @return
*/
private AVLNode<T> _leftRotation(AVLNode<T> w) {
AVLNode<T> x = w.rChild;
w.rChild = x.lChild;
x.lChild = w;
w.height = Math.max(_height(w.lChild), _height(w.rChild)) + 1;
x.height = Math.max(w.height, _height(x.rChild)) + 1;
return x;
}
private AVLNode<T> _rightRotation(AVLNode<T> x) {
AVLNode<T> w = x.lChild;
x.lChild = w.rChild;
w.rChild = x;
x.height = Math.max(_height(x.lChild), _height(x.rChild)) + 1;
w.height = Math.max(x.height, _height(w.lChild)) + 1;
return w;
}
// lr
private AVLNode<T> _left_right_ratation(AVLNode<T> p) {
p.lChild = _leftRotation(p.lChild);
return _rightRotation(p);
}
private AVLNode<T> _right_left_ratation(AVLNode<T> p) {
p.rChild = _rightRotation(p.rChild);
return _leftRotation(p);
}
private AVLNode<T> _insert(AVLNode<T> parent, T data) {
if (parent == null) {
parent = new AVLNode<T>(data);
}
int result = data.compareTo(parent.data);
if (result < 0) {
parent.lChild = _insert(parent.lChild, data);
if (_height(parent.lChild) - _height(parent.rChild) == 2) {
if (data.compareTo(parent.lChild.data) < 0) {
parent = _rightRotation(parent);
} else {
parent = _left_right_ratation(parent);
}
}
} else if (result > 0) {
parent.rChild = _insert(parent.rChild, data);
if (_height(parent.rChild) - _height(parent.lChild) == 2) {
if (data.compareTo(parent.rChild.data) > 0) {
parent = _leftRotation(parent);
} else {
parent = _right_left_ratation(parent);
}
}
} else {
// do nothing;
}
parent.height = Math.max(_height(parent.lChild), _height(parent.rChild)) + 1;
return parent;
}
}
public class Main {
public static void main(String[] args) {
AVLDTree<Integer> avlT = new AVLDTree<Integer>();
avlT.insert(3);
avlT.insert(2);
avlT.insert(1);
avlT.insert(4);
avlT.insert(5);
avlT.insert(6);
avlT.insert(7);
avlT.insert(10);
avlT.insert(9);
avlT.insert(8);
}
}
还没有写遍历代码,但可以通过debug来查看树插入数据后的内存情况。中序遍历结果应该是这样: