[求助]如果有人肯帮忙看看,那真是麻烦大家了,写了一个红黑树,可是有点问题。

2016-06-14 12:08:11 +08:00
 linux40

目前只测试了 inesert 和 erase 操作。 insert 操作完全正确(至少连续的 insert 操作,中间没有 erase ,没有任何问题), erase 操作(测试的是连续的删除操作,从 begin 开始删)会出现两种错误:

把 erase fix 注释掉后完全正常,并且与标准库的比较过。 测试的代码:

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dis(1, 50000);
    int arr[10000];
    for (int i = 0; i != 10000; ++i)
        arr[i] = dis(gen);
    glglT::multiset<int> g(arr, arr + 10000);
    auto git = g.begin();
    for (std::size_t i = 0; i != 5000; ++i)
        git = g.erase(git);

erase 的写法,真正 erase 的函数由于没有 fix 的话,是完全正常的,所以暂时不贴。

    iterator erase(const_iterator itr)
    {//erase 不移动值,只移动结点本身
        this->erase((itr++).curr);
        return static_cast<iterator>(itr);
    }

erase fix,之前判断了删除的node的颜色是黑色,才调用。

    void erase_fix(rebind_ptr p, bool is_left)
    {//表示删除的结点是其 parent 的左边还是右边, p 的 left 和 right 赋值正确了的,最大最小结点即 eot->l 和 eot->r 也赋值正确
        for (rebind_ptr black_p = is_left ? p->l : p->r; p != eot;) {
            if (black_p->is_red) {
                black_p->is_red = false;
                return;
            }
            rebind_ptr b = is_left ? p->r : p->l;
            if (b->is_red) {
                if (is_left) {
                    this->left_rotate(p, b);
                    b = p->r;
                } else {
                    this->right_rotate(p, b);
                    b = p->l;
                }
            }
            rebind_ptr c = is_left ? b->r : b->l;
            if (!c->is_red) {
                if (is_left ? !b->l->is_red : !b->r->is_red) {
                    b->is_red = true;
                    black_p = p;
                    p = p->p;
                    is_left = black_p == p->l;
                    continue;
                }
                is_left ? this->right_rotate(b, b->l) : this->left_rotate(b, b->r);
                b->is_red = true;
                c = b;
                b = b->p;
                b->is_red = false;
            }
            is_left ? this->left_rotate(p, b) : this->right_rotate(p, b);
            c->is_red = false;
            glglT::swap(p->is_red, b->is_red);
            break;
        }   eot->p->is_red = false;
    }

需要别的信息的话,我会在添加的。

1641 次点击
所在节点    C
3 条回复
linux40
2016-06-14 16:07:27 +08:00
顶一下?( ;∀;)
linux40
2016-06-14 16:32:53 +08:00
呃,知道了,有个地方忘改颜色了,我调试了两天呀( ;∀;)
lsmgeb89
2016-07-29 11:42:22 +08:00
写的时候就要逐步测试,最后 random 测的话,查起来很累。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/285586

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX