红黑树连接算法实现

问题描述

我最近一直在尝试根据 Wikipedia page 上提供的伪代码在 RB 树上实现连接操作。我重新创建了伪代码,以便我的代码几乎相同,即使使用相同的变量名称,但它仍然不起作用。连接操作将节点放置在正确的位置,但重新着色和旋转根本不起作用或破坏树。这是一个示例起始树:

enter image description here

然后在键 1000 上将其与键为 1001 的单个节点连接后,结果是这样的:

enter image description here

两个节点都已正确插入,但树中出现双红色节点且未修复。 在这种情况下,函数 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 (将#修改为@)