removeremove分成三种情况Q没有孩子节点的节点(即页?,单个孩子节点的节点,两个孩子节点的节?/p>
1)子节点可以直接删除
2)单个孩子节点的节点删除了Q让其下的孩子节点直接和其父亲节点相q?是孩子节点和祖父节点相q?
3)两个孩子节点的节点,Z保持排序状态,需要拿到这个节点的左子树的最大节Ҏ者右子树的最节点,得到q个节点的数据代替要删除的节点,
然后删除q个左子树的最大节Ҏ者右子树的最节点,因ؓ左子树的最大节Ҏ有右节点(有右节点的话Q他׃是最大的?,同理Q右子树的最节?/p>
没有左节点,所以要删除的这个节点只有一个或者没有孩子节点,只需要进?)或?)完成了?/p>
AVL?/h3>
在插入节Ҏ通过旋{(rotation)解决问题:
/**
* 插入一个元素到树里面,可能破坏了高度差Q需要找C个节点aQ该节点左子树和叛_树被破坏了,则需要对q个节点(q因子)
*
* 树进行^衡,有四U情?
*
* 1.a节点的左儿子的左子树插入
*
* 2.a节点的左儿子的右子树插入
*
* 3.a节点的右儿子的左子树插入
*
* 4.a节点的右儿子的右子树插入
*
*
* 1.4两种情况需要进行一ơ旋?br /> *
* 2.3两种情况需要进行两ơ旋?br /> *
* 旋{的目的是Z使插入节点的树的高度降低1Q所以只要求旋{q因子为根的树可以了
*/
在删除节点的时候:
/**
* 删除一个节点,扑ֈq因子Q他的左子树高度和右子树高度如果相差2的话Q就需要旋转,而且旋{后,q因子的节点ؓ根的树的高度肯定?br /> *
* 下降1Q这样^衡因子所在的树的高度下降1Q也有可能需要进行旋转调_q样调整一直到根节?br /> *
*/
代码如下Q?br />
package struct;
/**
* @author chenxiaohui
* @version 创徏旉Q?011-8-26
*
*
*/
public class AvlTree {
/**
*
* avl?树中每个节点的左子树和右子树的高度最多差1的二叉查找树
*
*
*
*/
public int height(AvlNode node) {
return node != null ? node.height : -1;
}
/**
*
*
* 插入一个元素到树里面,可能破坏了高度差Q需要找C个节点aQ该节点左子树和叛_树被破坏了,则需要对q个节点(q因子)
*
* 树进行^衡,有四U情?
*
* 1.a节点的左儿子的左子树插入
*
* 2.a节点的左儿子的右子树插入
*
* 3.a节点的右儿子的左子树插入
*
* 4.a节点的右儿子的右子树插入
*
*
* 1.4两种情况需要进行一ơ旋?br /> *
* 2.3两种情况需要进行两ơ旋?br /> *
* @param t
* @param tree
* @return
*/
public AvlNode insert(int t, AvlNode tree) {
if (tree == null)
return new AvlNode(t);
int cmp = compare(t, tree.element);
if (cmp < 0) {
// 左子?/span>
tree.leftChild = insert(t, tree.leftChild);
// 因ؓ左子树插入了节点Q那么左子树比右子树?Ҏavl树的性质Q插入了节点
// 要么高度差ؓ1Q要么高度差?Q所以当相差?Ӟ需要进行树的调?/span>
if ((height(tree.leftChild) - height(tree.reightChild)) == 2) {
// 当t比树左子树的元素q小的话Q就是在树的左子树的左边插入节点Q成为左子树的左子树Q需要一ơ旋?/span>
if (compare(t, tree.leftChild.element) < 0) {
tree = rotateLeftChild(tree);
} else {
// 当t比树左子树的元素q大的话Q就是在树的左子树的双插入节点Q成为左子树的右子树Q需要两ơ旋?/span>
tree = doubleRotateLeftChild(tree);
}
}
} else if (cmp > 0) {
// 叛_?/span>
tree.reightChild = insert(t, tree.reightChild);
if ((height(tree.reightChild) - height(tree.leftChild)) == 2) {
// 当t比树叛_树的元素q大的话Q就是在树的叛_树的双插入节点Q成为右子树的右子树Q需要一ơ旋?/span>
if (compare(t, tree.reightChild.element) > 0) {
tree = rotateRightChild(tree);
} else {
// 当t比树叛_树的元素q小的话Q就是在树的叛_树的左边插入节点Q成为右子树的左子树Q需要两ơ旋?/span>
tree = doubleRotateRightChild(tree);
}
}
} else {
// 树里面有q个?/span>
}
tree.height = Math
.max(height(tree.leftChild), height(tree.reightChild)) + 1;
return tree;
}
/**
* W?U情况需要进行顺旉旋{(x?
*
* @param k2
* @return
*/
private AvlNode rotateLeftChild(AvlNode k2) {
AvlNode k1 = k2.leftChild;
k2.leftChild = k1.reightChild;
k1.reightChild = k2;
k2.height = Math.max(height(k2.leftChild), height(k2.reightChild)) + 1;
k1.height = Math.max(height(k1.leftChild), height(k2)) + 1;
return k1;
}
/**
*
* W?U情况需要进行逆时针旋?左旋?
*
* @param k2
* @return
*/
private AvlNode rotateRightChild(AvlNode k2) {
AvlNode k1 = k2.reightChild;
k2.reightChild = k1.leftChild;
k1.leftChild = k2;
k2.height = Math.max(height(k2.leftChild), height(k2.reightChild)) + 1;
k1.height = Math.max(height(k1.reightChild), height(k2)) + 1;
return k1;
}
/**
* W?U情况需要进??左旋?
*
* @param k3
* @return
*/
private AvlNode doubleRotateLeftChild(AvlNode k3) {
AvlNode k1 = k3.leftChild;
k3.leftChild = rotateRightChild(k1);
return rotateLeftChild(k3);
}
/**
* W?U情况需要进??x?
*
* @param k3
* @return
*/
private AvlNode doubleRotateRightChild(AvlNode k3) {
AvlNode k1 = k3.reightChild;
k3.reightChild = rotateLeftChild(k1);
return rotateRightChild(k3);
}
public int compare(int a, int b) {
return a - b;
}
static class AvlNode {
private int element;
private int height;
private AvlNode leftChild;
private AvlNode reightChild;
AvlNode(int element) {
this(element, null, null);
}
AvlNode(int element, AvlNode left, AvlNode right) {
this.element = element;
this.leftChild = left;
this.reightChild = right;
}
}
public void sysout(AvlNode node) {
if (node != null) {
AvlNode a = node.leftChild;
sysout(a);
for (int i = 0; i < node.height; i++) {
System.out.print(" ");
}
System.out.print(node.element);
System.out.print("\n");
AvlNode b = node.reightChild;
sysout(b);
}
}
/**
* 删除一个节点,扑ֈq因子Q他的左子树高度和右子树高度如果相差2的话Q就需要旋转,而且旋{后,q因子的节点ؓ根的树的高度肯定?br /> *
* 下降1Q这样^衡因子所在的树的高度下降1Q也有可能需要进行旋转调_q样调整一直到根节?br /> *
* @param t
* @param tree
* @return
*/
public AvlNode delete(int t, AvlNode tree) {
if (tree == null)
return null;
int cmp = compare(t, tree.element);
if (cmp < 0) {
tree.leftChild = delete(t, tree.leftChild);
if ((height(tree.reightChild) - height(tree.leftChild)) == 2) {
if (tree.leftChild == null) {
tree = rotateRightChild(tree);
} else {
tree = doubleRotateRightChild(tree);
}
}
} else if (cmp > 0) {
tree.reightChild = delete(t, tree.reightChild);
if ((height(tree.leftChild) - height(tree.reightChild)) == 2) {
if (tree.reightChild == null) {
tree = rotateLeftChild(tree);
} else {
tree = doubleRotateLeftChild(tree);
}
}
} else if (cmp == 0) {
tree = null;
}
if (tree != null) {
tree.height = Math.max(height(tree.leftChild),
height(tree.reightChild)) + 1;
}
return tree;
}
public static void main(String[] args) {
AvlTree avlTree = new AvlTree();
AvlNode node = new AvlNode(20);
/*
* Random random = new Random(); for (int i = 0; i < 10; i++) { int y =
* random.nextInt(100) + 1; node = avlTree.insert(y, node); }
*/
node = avlTree.insert(8, node);
node = avlTree.insert(3, node);
node = avlTree.insert(10, node);
node = avlTree.insert(2, node);
node = avlTree.insert(5, node);
node = avlTree.insert(30, node);
node = avlTree.insert(50, node);
node = avlTree.insert(6, node);
node = avlTree.insert(20, node);
node = avlTree.insert(35, node);
node = avlTree.insert(43, node);
node = avlTree.insert(60, node);
node = avlTree.insert(18, node);
node = avlTree.insert(26, node);
node = avlTree.insert(33, node);
node = avlTree.insert(40, node);
node = avlTree.insert(45, node);
node = avlTree.insert(62, node);
// avlTree.sysout(node);
node = avlTree.delete(2, node);
avlTree.sysout(node);
}
}

]]>