DBD-SQLite2
view release on metacpan or search on metacpan
break;
case 2:
/* Check red-black property (1) */
if( !pNode->isBlack &&
( (pNode->pLeft && !pNode->pLeft->isBlack) ||
(pNode->pRight && !pNode->pRight->isBlack) )
){
char buf[128];
sprintf(buf, "Red node with red child at %p\n", pNode);
*msg = append_val(*msg, buf);
*msg = append_node(*msg, tree->pHead, 0);
*msg = append_val(*msg, "\n");
}
/* Check red-black property (2) */
{
int leftHeight = 0;
int rightHeight = 0;
if( pNode->pLeft ){
leftHeight += pNode->pLeft->nBlackHeight;
leftHeight += (pNode->pLeft->isBlack?1:0);
}
if( pNode->pRight ){
rightHeight += pNode->pRight->nBlackHeight;
rightHeight += (pNode->pRight->isBlack?1:0);
}
if( leftHeight != rightHeight ){
char buf[128];
sprintf(buf, "Different black-heights at %p\n", pNode);
*msg = append_val(*msg, buf);
*msg = append_node(*msg, tree->pHead, 0);
*msg = append_val(*msg, "\n");
}
pNode->nBlackHeight = leftHeight;
}
if( pNode->pParent ){
if( pNode == pNode->pParent->pLeft ) prev_step = 1;
else prev_step = 2;
}
pNode = pNode->pParent;
break;
default: assert(0);
}
}
}
/*
* Node pX has just been inserted into pTree (by code in sqliteRbtreeInsert()).
* It is possible that pX is a red node with a red parent, which is a violation
* of the red-black tree properties. This function performs rotations and
* color changes to rebalance the tree
*/
static void do_insert_balancing(BtRbTree *pTree, BtRbNode *pX)
{
/* In the first iteration of this loop, pX points to the red node just
* inserted in the tree. If the parent of pX exists (pX is not the root
* node) and is red, then the properties of the red-black tree are
* violated.
*
* At the start of any subsequent iterations, pX points to a red node
* with a red parent. In all other respects the tree is a legal red-black
* binary tree. */
while( pX != pTree->pHead && !pX->pParent->isBlack ){
BtRbNode *pUncle;
BtRbNode *pGrandparent;
/* Grandparent of pX must exist and must be black. */
pGrandparent = pX->pParent->pParent;
assert( pGrandparent );
assert( pGrandparent->isBlack );
/* Uncle of pX may or may not exist. */
if( pX->pParent == pGrandparent->pLeft )
pUncle = pGrandparent->pRight;
else
pUncle = pGrandparent->pLeft;
/* If the uncle of pX exists and is red, we do the following:
* | |
* G(b) G(r)
* / \ / \
* U(r) P(r) U(b) P(b)
* \ \
* X(r) X(r)
*
* BEFORE AFTER
* pX is then set to G. If the parent of G is red, then the while loop
* will run again. */
if( pUncle && !pUncle->isBlack ){
pGrandparent->isBlack = 0;
pUncle->isBlack = 1;
pX->pParent->isBlack = 1;
pX = pGrandparent;
}else{
if( pX->pParent == pGrandparent->pLeft ){
if( pX == pX->pParent->pRight ){
/* If pX is a right-child, do the following transform, essentially
* to change pX into a left-child:
* | |
* G(b) G(b)
* / \ / \
* P(r) U(b) X(r) U(b)
* \ /
* X(r) P(r) <-- new X
*
* BEFORE AFTER
*/
pX = pX->pParent;
leftRotate(pTree, pX);
}
/* Do the following transform, which balances the tree :)
* | |
* G(b) P(b)
* / \ / \
* P(r) U(b) X(r) G(r)
* / \
* X(r) U(b)
*
( run in 1.420 second using v1.01-cache-2.11-cpan-71847e10f99 )