问题描述
我最近一直在尝试根据 Wikipedia page 上提供的伪代码在 RB 树上实现连接操作。我重新创建了伪代码,以便我的代码几乎相同,即使使用相同的变量名称,但它仍然不起作用。连接操作将节点放置在正确的位置,但重新着色和旋转根本不起作用或破坏树。这是一个示例起始树:
然后在键 1000 上将其与键为 1001 的单个节点连接后,结果是这样的:
两个节点都已正确插入,但树中出现双红色节点且未修复。 在这种情况下,函数 joinRightRB 被调用,根据维基百科,当右孩子是红色并且右孩子的右孩子是红色时,它应该旋转树,这在这里不会发生。但是,将其更改为右孩子的左孩子只会修复某些情况并破坏其他情况,因此我无法判断这里出了什么问题,而且我确定我错的可能性更大,而不是维基百科。正如我之前所说,我的代码几乎是伪代码的相同表示:
struct RBTree* join(struct RBTree *left,struct RBTree *right,void *key,int (*compare)(void *,void *),size_t key_size,size_t value_size)
{
if(black_height(left->root) > black_height(right->root)){
struct Node* t_prim = __joinRight(left->root,key,right->root);
if(t_prim->color == RED && t_prim->right->color == RED) {
t_prim->color = BLACK;
}
return create_tree(t_prim,compare,key_size,value_size);
} else if(black_height(right->root) > black_height(left->root)) {
struct Node* t_prim = __joinLeft(left->root,right->root);
if(t_prim->color == RED && t_prim->left->color == RED) {
t_prim->color = BLACK;
}
return create_tree(t_prim,value_size);
} else if(left->root->color == BLACK && right->root->color == BLACK) {
return create_tree(__create_node(left,RED,right),value_size);
} else {
return create_tree(__create_node(left,BLACK,value_size);
}
}
struct Node *__joinRight(struct Node *t_l,void *k,struct Node *t_r)
{
if(black_height(t_l) == black_height(t_r)) {
return __create_node(t_l,k,t_r);
} else {
struct Node* l_prim = t_l->left;
struct Node* r_prim = t_l->right;
void* k_prim = t_l->key;
enum color_t c_prim = t_l->color;
struct Node* t_prim = __create_node(l_prim,k_prim,c_prim,__joinRight(r_prim,t_r));
if (c_prim == BLACK && t_prim->right->color == RED && t_prim->right->right->color == RED) {
t_prim->right->right->color = BLACK;
rotateTree(NULL,t_prim,LEFT);
}
return t_prim;
}
}
struct Node *__joinLeft(struct Node *t_l,t_r);
} else {
struct Node *l_prim = t_r->left;
struct Node *r_prim = t_r->right;
void *k_prim = t_r->key;
enum color_t c_prim = t_r->color;
struct Node* t_prim = __create_node(__joinLeft(t_l,l_prim),r_prim);
if (c_prim == BLACK && t_prim->left->color == RED && t_prim->left->left->color == RED) {
t_prim->left->left->color = BLACK;
rotateTree(NULL,RIGHT);
}
return t_prim;
}
}
struct Node* rotateTree(struct RBTree* t,struct Node* p,enum direction_t direction)
{
struct Node* g = p->parent;
struct Node* s = direction == RIGHT ? p->left : p->right;
struct Node* c = &nil;
assert(p != &nil);
c = direction == RIGHT ? p->right : p->left;
if(direction == RIGHT) {
p->left = c;
} else {
p->right = c;
}
if(c != &nil) {
c->parent = p;
}
if(direction == RIGHT) {
s->right = p;
} else {
s->left = p;
}
p->parent = s;
s->parent = g;
if(g != &nil) {
if(p == g->right) {
g->right = s;
} else {
g->left = s;
}
}
return s;
}
unsigned black_height(struct Node* node)
{
struct Node* current = node;
unsigned b_height = 0;
while(current != &nil) {
if(current->color == BLACK) {
++b_height;
}
if(current->left != &nil) {
current = current->left;
} else {
current = current->right;
}
}
return b_height;
}
函数 __create_node 只创建一个具有左右子节点、颜色和键作为参数提供的节点(父节点为空)。旋转函数是一团糟,因为我试图尽可能接近地从伪代码复制该函数。几天来,我一直在试图找出问题所在,但我完全没有想法。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)