我正在自己写红黑树。但是当我测试涉及根旋转的旋转时,它会失去参考。
树形结构:
45
/ \
40x 70
/ \ /
7 41 50
/ \
6 39
旋转逻辑说: “以45(根)作为顶部旋转,朝向提升X的方向(即40)”
所以这意味着正确旋转,结果应如下所示:
40x
/ \
7 45
/ \ / \
6 39 41 70
/
50
假设节点45是祖父母,7是父母,41是当前。 (我知道顺序没有意义,但请忽略,这是因为我已经旋转了一次)
代码:
//current is node 45
//parent is node 7
//grandparent is node 45 (root)
//first detach cross node (i.e. 41)
Node crossNode2 = grandparent.left.right;
grandparent.left.right = null; //detach
45
/ \
40x 70
/ \ /
7 null 50
/ \
6 39
grandparent.left = null;
45
/ \
null 70
/
50
current.right = grandparent;
40
/ \
7 45
/ \ / \
6 39 null 70
/
50
grandparent.left = crossNode2; //attach
40
/ \
7 45
/ \ / \
6 39 41 70
/
50
但不知何故,这段代码不起作用。当我测试时:
preorder
45, 39, 70, 50
breadth-first
45, 39, 70, 50
所以我认为结果实际上是:
45
/ \
39 70
/
50
有人能给我提示我的轮换代码有什么问题吗?
答案 0 :(得分:3)
在节点Q上执行右旋转的步骤:
您错过了所提供代码中的粗体步骤。我认为你的问题是你正在将涉及根节点的轮换视为一种特殊情况。显然,如果Q是根且其父级为null
,则无法执行此操作。尝试创建一个“头”节点,谁是正确的节点是根。这允许涉及根的旋转使用常规算法工作。
public static void rotateRight(Node node) {
assert(!node.isLeaf() && !node.left.isLeaf());
final Node child = node.left;
node.setLeft(child.right);
if (node.isRightChild())
node.parent.setRight(child);
else node.parent.setLeft(child);
child.setRight(node);
}
setRight
和setLeft
保持parent
参考更新以及更新right
和left
的节点。 node.isRightNode()
来电可以只是(node.parent.right == node)
。
答案 1 :(得分:0)
根据Gunslinger47的回答,我也测试了左旋转版本。 代码工作正常。 (如果没有,请告诉我。)
还在我的网站上记录:)
http://masatosan.com/btree.jsp
public static void rotateLeft(Node node) {
assert(!node.isLeaf() && !node.right != null);
final Node child = node.right;
node.setRight(child.left);
if(node.isLeftChild()) {
node.parent.setLeft(child);
}
else {
node.parent.setRight(child);
}
chlid.setLeft(node);
}