我对Wikipedia上的插入操作代码感到困惑。
简而言之,我想不出一个示例,在插入后必须进行重新跟踪。由于插入总是发生在叶节点中,因此将Z
插入到节点X
中。第一次/最早违反AVL树的不变式(平衡因子必须在[-1,1]之内)只能在parent(X)
中发生。重新平衡仅包含Z
,X
和parent(X)
的小子树后,此小子树的高度将与以前相同,并且对所有其他子树没有任何影响节点。
为什么我们需要一个一直循环到根的循环?
for (X = parent(Z); X != null; X = parent(Z)) { // Loop (possibly up to the root)
// BalanceFactor(X) has to be updated:
if (Z == right_child(X)) { // The right subtree increases
if (BalanceFactor(X) > 0) { // X is right-heavy
// ===> the temporary BalanceFactor(X) == +2
// ===> rebalancing is required.
G = parent(X); // Save parent of X around rotations
if (BalanceFactor(Z) < 0) // Right Left Case (see figure 5)
N = rotate_RightLeft(X, Z); // Double rotation: Right(Z) then Left(X)
else // Right Right Case (see figure 4)
N = rotate_Left(X, Z); // Single rotation Left(X)
// After rotation adapt parent link
} else {
if (BalanceFactor(X) < 0) {
BalanceFactor(X) = 0; // Z’s height increase is absorbed at X.
break; // Leave the loop
}
BalanceFactor(X) = +1;
Z = X; // Height(Z) increases by 1
continue;
}
} else { // Z == left_child(X): the left subtree increases
if (BalanceFactor(X) < 0) { // X is left-heavy
// ===> the temporary BalanceFactor(X) == –2
// ===> rebalancing is required.
G = parent(X); // Save parent of X around rotations
if (BalanceFactor(Z) > 0) // Left Right Case
N = rotate_LeftRight(X, Z); // Double rotation: Left(Z) then Right(X)
else // Left Left Case
N = rotate_Right(X, Z); // Single rotation Right(X)
// After rotation adapt parent link
} else {
if (BalanceFactor(X) > 0) {
BalanceFactor(X) = 0; // Z’s height increase is absorbed at X.
break; // Leave the loop
}
BalanceFactor(X) = –1;
Z = X; // Height(Z) increases by 1
continue;
}
}
// After a rotation adapt parent link:
// N is the new root of the rotated subtree
// Height does not change: Height(N) == old Height(X)
parent(N) = G;
if (G != null) {
if (X == left_child(G))
left_child(G) = N;
else
right_child(G) = N;
break;
} else {
tree->root = N; // N is the new root of the total tree
break;
}
// There is no fall thru, only break; or continue;
}
// Unless loop is left via break, the height of the total tree increases by 1.