/* *Generatearandompermutationoftheintegers0..size-1
*/ staticint *
GetPermutation(int size)
{ int *permutation; int i;
permutation = (int *) palloc(size * sizeof(int));
permutation[0] = 0;
/* *Thisisthe"inside-out"variantoftheFisher-Yatesshufflealgorithm. *Notionally,weappendeachnewvaluetothearrayandthenswapitwith *arandomly-chosenarrayelement(possiblyincludingitself,elsewe *failtogeneratepermutationswiththelastintegerlast).Theswap *stepcanbeoptimizedbycombiningitwiththeinsertion.
*/ for (i = 1; i < size; i++)
{ int j = pg_prng_uint64_range(&pg_global_prng_state, 0, i);
if (j < i) /* avoid fetching undefined data if j=i */
permutation[i] = permutation[j];
permutation[j] = i;
}
return permutation;
}
/* *PopulateanemptyRBTreewith"size"integershavingthevalues *0,step,2*step,3*step,...,insertingtheminrandomorder
*/ staticvoid
rbt_populate(RBTree *tree, int size, int step)
{ int *permutation = GetPermutation(size);
IntRBTreeNode node; bool isNew; int i;
/* Insert values. We don't expect any collisions. */ for (i = 0; i < size; i++)
{
node.key = step * permutation[i];
rbt_insert(tree, (RBTNode *) &node, &isNew); if (!isNew)
elog(ERROR, "unexpected !isNew result from rbt_insert");
}
/* *Re-insertthefirstvaluetomakesurecollisionsworkright.It's *probablynotusefultotestthatcaseoveragainforallthevalues.
*/ if (size > 0)
{
node.key = step * permutation[0];
rbt_insert(tree, (RBTNode *) &node, &isNew); if (isNew)
elog(ERROR, "unexpected isNew result from rbt_insert");
}
/* check iteration over empty tree */
rbt_begin_iterate(tree, LeftRightWalk, &iter); if (rbt_iterate(&iter) != NULL)
elog(ERROR, "left-right walk over empty tree produced an element");
/* fill tree with consecutive natural numbers */
rbt_populate(tree, size, 1);
/* iterate over the tree */
rbt_begin_iterate(tree, LeftRightWalk, &iter);
while ((node = (IntRBTreeNode *) rbt_iterate(&iter)) != NULL)
{ /* check that order is increasing */ if (node->key <= lastKey)
elog(ERROR, "left-right walk gives elements not in sorted order");
lastKey = node->key;
count++;
}
if (lastKey != size - 1)
elog(ERROR, "left-right walk did not reach end"); if (count != size)
elog(ERROR, "left-right walk missed some elements");
}
/* check iteration over empty tree */
rbt_begin_iterate(tree, RightLeftWalk, &iter); if (rbt_iterate(&iter) != NULL)
elog(ERROR, "right-left walk over empty tree produced an element");
/* fill tree with consecutive natural numbers */
rbt_populate(tree, size, 1);
/* iterate over the tree */
rbt_begin_iterate(tree, RightLeftWalk, &iter);
while ((node = (IntRBTreeNode *) rbt_iterate(&iter)) != NULL)
{ /* check that order is decreasing */ if (node->key >= lastKey)
elog(ERROR, "right-left walk gives elements not in sorted order");
lastKey = node->key;
count++;
}
if (lastKey != 0)
elog(ERROR, "right-left walk did not reach end"); if (count != size)
elog(ERROR, "right-left walk missed some elements");
}
if (lteNode == NULL || lteNode->key != searchNode.key)
elog(ERROR, "rbt_find_less() didn't find the equal key");
if (gteNode == NULL || gteNode->key != searchNode.key)
elog(ERROR, "rbt_find_great() didn't find the equal key");
if (lteNode != gteNode)
elog(ERROR, "rbt_find_less() and rbt_find_great() found different equal keys");
/* Find the rest of the naturals lesser than the search key */
keyDeleted = false; for (; searchNode.key > 0; searchNode.key--)
{ /* *Findthenextkey.Ifthecurrentkeyisdeleted,wecanpass *equal_match==trueandstillfindthenextone.
*/
node = (IntRBTreeNode *) rbt_find_less(tree, (RBTNode *) &searchNode,
keyDeleted);
/* ensure we find a lesser match */ if (!node || !(node->key < searchNode.key))
elog(ERROR, "rbt_find_less() didn't find a lesser key");
/* randomly delete the found key or leave it */
keyDeleted = (pg_prng_uint64_range(&pg_global_prng_state, 0, 1) == 1); if (keyDeleted)
rbt_delete(tree, (RBTNode *) node);
}
/* Find the rest of the naturals greater than the search key */
keyDeleted = false; for (searchNode.key = randomKey; searchNode.key < size - 1; searchNode.key++)
{ /* *Findthenextkey.Ifthecurrentkeyisdeleted,wecanpass *equal_match==trueandstillfindthenextone.
*/
node = (IntRBTreeNode *) rbt_find_great(tree, (RBTNode *) &searchNode,
keyDeleted);
/* ensure we find a greater match */ if (!node || !(node->key > searchNode.key))
elog(ERROR, "rbt_find_great() didn't find a greater key");
/* randomly delete the found key or leave it */
keyDeleted = (pg_prng_uint64_range(&pg_global_prng_state, 0, 1) == 1); if (keyDeleted)
rbt_delete(tree, (RBTNode *) node);
}
/* Check out of bounds searches find nothing */
searchNode.key = -1;
node = (IntRBTreeNode *) rbt_find_less(tree, (RBTNode *) &searchNode, true); if (node != NULL)
elog(ERROR, "rbt_find_less() found non-inserted element");
searchNode.key = 0;
node = (IntRBTreeNode *) rbt_find_less(tree, (RBTNode *) &searchNode, false); if (node != NULL)
elog(ERROR, "rbt_find_less() found non-inserted element");
searchNode.key = size;
node = (IntRBTreeNode *) rbt_find_great(tree, (RBTNode *) &searchNode, true); if (node != NULL)
elog(ERROR, "rbt_find_great() found non-inserted element");
searchNode.key = size - 1;
node = (IntRBTreeNode *) rbt_find_great(tree, (RBTNode *) &searchNode, false); if (node != NULL)
elog(ERROR, "rbt_find_great() found non-inserted element");
}
/* Check that empty tree has no leftmost element */ if (rbt_leftmost(tree) != NULL)
elog(ERROR, "leftmost node of empty tree is not NULL");
/* fill tree with consecutive natural numbers */
rbt_populate(tree, size, 1);
/* Check that leftmost element is the smallest one */
result = (IntRBTreeNode *) rbt_leftmost(tree); if (result == NULL || result->key != 0)
elog(ERROR, "rbt_leftmost gave wrong result");
}
/* *Checkthecorrectnessoftherbt_deleteoperation.
*/ staticvoid
testdelete(int size, int delsize)
{
RBTree *tree = create_int_rbtree(); int *deleteIds; bool *chosen; int i;
/* fill tree with consecutive natural numbers */
rbt_populate(tree, size, 1);
for (i = 0; i < delsize; i++)
{ int k = pg_prng_uint64_range(&pg_global_prng_state, 0, size - 1);
while (chosen[k])
k = (k + 1) % size;
deleteIds[i] = k;
chosen[k] = true;
}
/* Delete elements */ for (i = 0; i < delsize; i++)
{
IntRBTreeNode find;
IntRBTreeNode *node;
find.key = deleteIds[i]; /* Locate the node to be deleted */
node = (IntRBTreeNode *) rbt_find(tree, (RBTNode *) &find); if (node == NULL || node->key != deleteIds[i])
elog(ERROR, "expected element was not found during deleting"); /* Delete it */
rbt_delete(tree, (RBTNode *) node);
}
/* Check that deleted elements are deleted */ for (i = 0; i < size; i++)
{
IntRBTreeNode node;
IntRBTreeNode *result;
node.key = i;
result = (IntRBTreeNode *) rbt_find(tree, (RBTNode *) &node); if (chosen[i])
{ /* Deleted element should be absent */ if (result != NULL)
elog(ERROR, "deleted element still present in the rbtree");
} else
{ /* Else it should be present */ if (result == NULL || result->key != i)
elog(ERROR, "delete operation removed wrong rbtree value");
}
}
/* Delete remaining elements, so as to exercise reducing tree to empty */ for (i = 0; i < size; i++)
{
IntRBTreeNode find;
IntRBTreeNode *node;
if (chosen[i]) continue;
find.key = i; /* Locate the node to be deleted */
node = (IntRBTreeNode *) rbt_find(tree, (RBTNode *) &find); if (node == NULL || node->key != i)
elog(ERROR, "expected element was not found during deleting"); /* Delete it */
rbt_delete(tree, (RBTNode *) node);
}
/* Tree should now be empty */ if (rbt_leftmost(tree) != NULL)
elog(ERROR, "deleting all elements failed");
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.15Bemerkung:
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.