所以我的功能是在BST中旋转我的节点:
void BST::rotate_with_left_child(BNode *&t){
BNode *t1 = t->left;
t->left = t1->right;
t1->right = t;
t->node_height = max(height(t->left),height(t->right))+1;
t1->node_height = max(height(t1->left),t->node_height)+1;
t = t1;
}
void BST::double_rotate_with_left_child(BNode *&t){
rotate_with_right_child(t->left);
rotate_with_left_child(t);
}
void BST::rotate_with_right_child(BNode *&t){
BNode *t1 = t->right;
t->right = t1->left;
t1->left = t;
t->node_height = max(height(t->right),height(t->left))+1;
t1->node_height = max(height(t1->right),t->node_height)+1;
t = t1;
}
void BST::double_rotate_with_right_child(BNode *&t){
rotate_with_left_child(t->right);
rotate_with_right_child(t);
}
并说我发现了一个我想要旋转到树根的节点。我将如何编写一个函数来执行此操作?
答案 0 :(得分:1)
注意:以下代码根本未经过测试。它只是说明了这些想法。代码一直在底层。
假设:
我假设您通过某种搜索例程获取节点。现在,我们的想法就是维持:
例如,给定这棵树:
15 / \ 2 35 / \ 28 42 / \ 19 31
我们搜索了树内的密钥19
。现在,我们希望将19一直旋转到顶部。
NodeStack
,从堆栈底部到顶部的一堆节点:[15, 35, 28, 19]
< - 堆栈顶部
DirStack
,遍历了一堆链接路线:[RIGHT, LEFT, LEFT]
< - 堆栈顶部
我们假设搜索命中此处。所以我们要做的第一件事是检索NodeStack
的最顶层元素,这是我们想要旋转到顶部的节点。在这种情况下,它是具有键19
的节点。完成此步骤后,两个堆栈都显示为:
NodeStack
:[15, 35, 28]
< - 堆栈顶部
DirStack
:[RIGHT, LEFT, LEFT]
< - 堆栈顶部
接下来,主循环运行直到DirStack
为空。我们从两个堆栈中弹出一个元素。从NodeStack
弹出的元素是我们希望旋转到顶部的节点的父节点,从DirStack
弹出的元素表示从刚刚弹出的节点到未来根节点的链接方向
在循环的第一次迭代中,我们有节点28
和链接方向LEFT
,因此节点19
是节点28
的左子节点。
应该不难看出我们应该向刚刚弹出的方向旋转,所以我们应该在方向为RIGHT
的情况下向左旋转父节点,并且如果方向旋转父节点是LEFT
。由于此处的方向为LEFT
,因此我们将父节点28
向右旋转。这可以通过调用节点rotate_with_left_child
上的28
函数来实现。
树成为
15 / \ 2 35 / \ 19 42 \ 28 \ 31
请注意28
成为了正确的孩子,因此这是正确的轮换。我很确定这是正确的术语。由于维基百科现在已经关闭,我无法验证这一点,但这个问题表明我使用了正确的术语:
Code with explanation for binary tree rotation (left OR right)
现在的筹码状态:
NodeStack
:[15, 35]
< - 堆栈顶部
DirStack
:[RIGHT, LEFT]
< - 堆栈顶部
堆栈不为空,因此我们从两个堆栈中弹出35
和LEFT
。我们使用节点35
上的 rotate_with_left_child 函数执行正确的旋转,以获取此树:
15 / \ 2 19 \ 35 / \ 28 42 \ 31
我们的节点现在更接近成为root。立即堆叠:
NodeStack
:[15]
DirStack
:[RIGHT]
我们弹出节点15
和方向RIGHT
。现在,我们使用节点rotate_with_right_child
上的15
函数执行左旋转,然后我们获取最后一棵树:
19 / \ 15 35 / / \ 2 28 42 \ 31
Tadah!我们现在完成了。这是代码,使用STL中的std::stack
。
// NOTE: None of the code here is tested, so some errors are expected.
// Used to indicate direction of links traversed during the search
enum Direction {
LEFT, RIGHT
};
// This function rotates the node at the top of nodeStack to the root of the tree.
// It assumes that the nodeStack is non-empty, and that nodeStack has one more
// element than dirStack
//
// nodeStack - stack of nodes encountered during search
// dirStack - direction of links traversed during search
void rotate_to_top(stack<BSTNode *>& nodeStack, stack<Direction>& dirStack) {
// remove the future root node. actually this assignment is not needed
// NOTE: You might also want to check if the nodeStack is empty before doing this
BSTNode* root = nodeStack.top();
nodeStack.pop();
// main loop. this is done until the dirStack is empty
while (!dirStack.empty()) {
Direction d = dirStack.top();
dirStack.pop();
BSTNode *par = nodeStack.top();
nodeStack.top();
// perform the proper rotation
if (d == LEFT) {
rotate_with_left_child(par);
} else {
rotate_with_right_child(par);
}
}
}
希望有帮助=)