RedBlack树实施

时间:2015-06-02 14:42:56

标签: c++ algorithm data-structures tree

我已经实现了一个红黑树,然后在其中插入了1,2,3,4,5,6,7,8,9,10。但似乎我的树不平衡,因为预订遍历如下所示:4,2,1,3,6,5,8,7,9,10和有序遍历:1,2,3,4,5,6,7,8,9,10。这意味着根是4,树不平衡!这是我的代码。

void RedBlackTree::leftRotate(RedBlackTreeNode * x){
    RedBlackTreeNode *y = x->right; //set y
    y = x->right;
    x->right = y->left;
    if (y->left != nilLeaf)
        y->left->p = x;
    y->p = x->p;
    if (x->p == nilLeaf)
        root = y;
    else if (x == x->p->left)
        x->p->left = y;
    else x->p->right = y;
    y->left = x;
    x->p = y;
}

void RedBlackTree::rightRotate(RedBlackTreeNode * x){
    RedBlackTreeNode *y = x->left; //set y
    y = x->left;
    x->left = y->right;
    if (y->right != nilLeaf)
        y->right->p = x;
    y->p = x->p;
    if (x->p == nilLeaf)
        root = y;
    else if (x == x->p->right)
        x->p->right = y;
    else x->p->left = y;
    y->right = x;
    x->p = y;
}

void RedBlackTree::insert(const Point &newItem){
    size++;
    if (empty){
        root->key = newItem;
        empty = false;
        return;
    }

    RedBlackTreeNode * z = new RedBlackTreeNode; 
    z->key = newItem;
    z->right = z->left = z->p = nilLeaf;

    RedBlackTreeNode *y = nilLeaf;// = new RedBlackTreeNode;
    RedBlackTreeNode *x = root;// = new RedBlackTreeNode;

    while (x != nilLeaf)
    {
        y = x;
        if (z->key < x->key)
            x = x->left;
        else
            x = x->right;
    }
    z->p = y;
    if (y == nilLeaf)
        root = z;
    else if (z->key < y->key)
        y->left = z;
    else
        y->right = z;

    z->left = nilLeaf;
    z->right = nilLeaf;
    z->color = RedBlackTreeNode::Red;

    insertFixUp(z);
}

void RedBlackTree::insertFixUp(RedBlackTreeNode* z){
    while (z->p->color == RedBlackTreeNode::Red)
    {
        if (z->p == z->p->p->left)
        {
            RedBlackTreeNode* y = z->p->p->right;
            if (y->color == RedBlackTreeNode::Red)
            {
                z->p->color = RedBlackTreeNode::Black;
                y->color = RedBlackTreeNode::Black;
                z->p->p->color = RedBlackTreeNode::Red;
                z = z->p->p;
            }
            else if (z == z->p->right)
            {
                z = z->p;
                leftRotate(z);
            }
            else{
                z->p->color = RedBlackTreeNode::Black;
                z->p->p->color = RedBlackTreeNode::Red;
                rightRotate(z->p->p);
            }
        }
        else if (z->p == z->p->p->right)
        {
            RedBlackTreeNode* y = z->p->p->left;
            if (y->color == RedBlackTreeNode::Red)
            {
                z->p->color = RedBlackTreeNode::Black;
                y->color = RedBlackTreeNode::Black;
                z->p->p->color = RedBlackTreeNode::Red;
                z = z->p->p;
            }
            else if (z == z->p->left)
            {
                z = z->p;
                rightRotate(z);                             //**
            }
            else{
                z->p->color = RedBlackTreeNode::Black;
                z->p->p->color = RedBlackTreeNode::Red;
                leftRotate(z->p->p);                        //**
            }
        }
    }
    root->color = RedBlackTreeNode::Black;
}

但我很确定insertFixUp有问题。因为此代码适用于大多数示例,但在某些情况下(如上例所示),节点高度之间的差异将大于2。

编辑:如果我在其中插入一些随机数,这段代码就可以了。当我在其中插入已排序的数字时会出现问题。

1 个答案:

答案 0 :(得分:2)

此代码没有任何问题。根据{{​​3}}:

'这些约束强制执行红黑树的关键属性:从根到最远叶子的路径不超过从根到最近叶子的路径的两倍。结果是树大致高度平衡'

所以4作为根是没有错的。尝试在树中插入更多数字,您将看到,根将发生变化,并且提到的属性将始终保持。