节点数据结构:
class Node {
int balanceDegree;//结点有平衡度(左子树高 - 右子树高), 在 [-1,01] 表示当前节点是平衡的
int val;
Node left,right,parent;// 左/右子树,parent指向父节点
}
插入数据需要调节平衡度,
(1) 插入节点 i
(2)从i节点开始向上回溯到根节点
(3)如果i节点是其父节点的左子树 则父节点平衡度+1 否则 父节点平衡度-1
(4) 如果 父节点平衡度为0 ,则执行 (7)
(5) 判断父节点平衡度是否在 [-1,0,1]之间,若不在,调整父节点的平衡度,执行(7)
(6) i=i.parent 执行(3)
(7)退出
调整节点的平衡度:
旋转,LL型(节点平衡度是2,左子树平衡度为 1) 通过右旋转达到平衡,LR(节点平衡度是2,左子树平衡度为 -1) 能过左旋转转成 LL 型
RR型(节点平衡度是-2,右子树平衡度为 -1) 通过左 旋转达到平衡,RL(节点平衡度是-2,右子树平衡度为 1) 能过右旋转转成 RR型
LR->LL ->平衡
RL->RR->平衡
旋转时要注意各节点的父指针及左右子树的设置
class Node {
int val, balanceDegree;
Node left, right, parent;
public Node(int val) {
this.val = val;
this.left = this.right = this.parent = null;
}
public int getbalanceDegree() {
return this.balanceDegree;
}
public String toString() {
return "[" + this.val + "," + this.getbalanceDegree() + "," + (this.parent == null ? "null" : this.parent.val)
+ "]";
}
}
public class AVLTree {
Node root;
public AVLTree() {
this.root = null;
}
private void _midTravel(Node n) {
if (n == null)
return;
this._midTravel(n.left);
System.out.print(n.toString() + " ");
this._midTravel(n.right);
}
public void midTravel() {
this._midTravel(root);
}
public void setChildrenParent(Node n) {
if (n == null)
return;
if (n.left != null)
n.left.parent = n;
if (n.right != null)
n.right.parent = n;
}
public Node rightRotate(Node node) {
if (node == null || node.left == null)
return node;
Node l = node.left;
node.left = l.right;
l.right = node;
l.parent = node.parent;
node.parent = l;
if (l.parent != null) {
if (l.parent.left == node) {
l.parent.left = l;
} else {
l.parent.right = l;
}
}
this.setChildrenParent(l.left);
this.setChildrenParent(l.right);
return l;
}
public Node leftRotate(Node node) {
if (node == null || node.right == null)
return node;
Node r = node.right;
node.right = r.left;
r.left = node;
r.parent = node.parent;
node.parent = r;
if (r.parent != null) {
if (r.parent.left == node) {
r.parent.left = r;
} else {
r.parent.right = r;
}
}
this.setChildrenParent(r.left);
this.setChildrenParent(r.right);
return r;
}
public void delVal(int val) {
}
public void insertVal(int val) {
if (root == null) {
this.root = new Node(val);
} else {
Node n = this.root, p = n;
Node i = new Node(val);
while (n != null) {
p = n;
if (n.val >= val) {
n = n.left;
} else {
n = n.right;
}
}
i.parent = p;
if (p.val > val)
p.left = i;
else
p.right = i;
/**/
while ((p = i.parent) != null) {
if (p.left == i)
p.balanceDegree++;
else
p.balanceDegree--;
// 树的高度不变,直接退出循环
if (p.balanceDegree == 0)
break;
if (p.balanceDegree == 2) {
if (p.left != null && p.left.balanceDegree == 1) {
// LL型
p = this.rightRotate(p);
} else {
// LR型
this.leftRotate(p.left);
p = this.rightRotate(p);
p.left.balanceDegree = p.balanceDegree >= 0 ? 0 : 1;
}
p.balanceDegree = 0;
p.right.balanceDegree = 0;
break;
} else if (p.balanceDegree == -2) {
if (p.left != null && p.left.balanceDegree == 1) {
// RL型
this.rightRotate(p.right);
p = this.leftRotate(p);
p.right.balanceDegree = p.balanceDegree >= 0 ? 0 : 1;
} else {
// RR型
p = this.leftRotate(p);
}
i = p.left;
p.balanceDegree = 0;
i.balanceDegree = 0;
break;
}
i = p;
p = i.parent;
}
while (this.root.parent != null)
this.root = this.root.parent;
}
System.out.println("insert :" + val);
this.leveleTravle();
System.out.println("---------------");
}
public void leveleTravle() {
if (this.root == null)
return;
List<Node> q = new ArrayList<Node>();
List<Node> q1 = new ArrayList<Node>();
List<Node> t;
q.add(this.root);
while (!q.isEmpty()) {
for (Node n : q) {
if (n == null) {
System.out.print("[#]\t");
continue;
}
System.out.print(n.toString() + "\t");
q1.add(n.left);
q1.add(n.right);
}
q.clear();
t = q1;
q1 = q;
q = t;
System.out.println();
}
}
public void insertVals(int[] data) {
for (int d : data) {
this.insertVal(d);
}
}
private int _hight(Node n) {
if (n == null)
return 0;
return 1 + Math.max(this._hight(n.left), this._hight(n.right));
}
public int hight() {
return this._hight(this.root);
}
public static void main(String[] args) {
AVLTree tree = new AVLTree();
tree.insertVals(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 });
System.out.println(tree.hight());
tree.midTravel();
// System.out.println();
// tree.leveleTravle();
}
}