3 * Checking red-black trees
5 * (c) 2024 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Xyla, a library of binary trees.
12 * Xyla is free software: you can redistribute it and/or modify it under
13 * the terms of the GNU Lesser General Public License as published by the
14 * Free Software Foundation; either version 3 of the License, or (at your
15 * option) any later version.
17 * Xyla is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
20 * License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with Xyla. If not, see <https://www.gnu.org/licenses/>.
26 /*----- Header files ------------------------------------------------------*/
31 /*----- Data structures ---------------------------------------------------*/
41 /*----- Main code ---------------------------------------------------------*/
43 static int chkrb(unsigned op, const struct xyla_bt_check *chk)
45 /* Check the red-black balance properties for a node. */
47 struct xyla_bt_nodecls *cls = chk->cls;
48 struct chkstate *st = chk->state;
49 const struct xyla_rb_node *node, *parent;
50 struct nodeinfo *node_info, *left_info, *right_info;
55 case XYLA_CHKOP_BEFORE:
56 node = CONST_RB_NODE(chk->node); parent = CONST_RB_NODE(chk->parent);
57 if (node->rb.f&XYLA_RBF_RED) {
58 if (chk->pos == XYLA_BTPOS_ROOT) {
60 xyla_bt_bughdr("XYLA-RB", chk->root, chk->fp);
61 fputs("root ", chk->fp);
62 xyla_bt_printnode(cls, &node->bt, chk->fp);
63 fputs(" is red\n", chk->fp);
66 } else if (parent->rb.f&XYLA_RBF_RED) {
68 xyla_bt_bughdr("XYLA-RB", chk->root, chk->fp);
69 fputs("red ", chk->fp);
70 xyla_bt_printnode(cls, &node->bt, chk->fp);
71 fputs(" has red parent ", chk->fp);
72 xyla_bt_printnode(cls, &parent->bt, chk->fp);
80 case XYLA_CHKOP_AFTER:
81 node_info = chk->node_info;
82 left_info = chk->left_info; right_info = chk->right_info;
83 node = CONST_RB_NODE(chk->node);
84 lht = left_info ? left_info->ht : 0;
85 rht = right_info ? right_info->ht : 0;
86 if (lht == -1 || rht == -1) { ht = -1; goto skip_htchk; }
89 xyla_bt_bughdr("XYLA-RB", chk->root, chk->fp);
90 xyla_bt_printnode(cls, &node->bt, chk->fp);
92 " left black-height %d /= %d right black-height\n",
95 ht = -1; rc = XYLA_RC_BAD; goto skip_htchk;
97 ht = lht + (node->rb.f&XYLA_RBF_RED ? 0 : 1);
98 if (chk->pos == XYLA_BTPOS_ROOT &&
99 st->blkht != -1 && ht != st->blkht) {
101 xyla_bt_bughdr("XYLA-RB", chk->root, chk->fp);
102 fputs("root ", chk->fp);
103 xyla_bt_printnode(cls, &node->bt, chk->fp);
104 fprintf(chk->fp, " black-height %d /= %d expected\n",
107 ht = -1; rc = XYLA_RC_BAD; goto skip_htchk;
116 int xyla_rb_check(struct xyla_bt_nodecls *cls,
117 struct xyla_bt_node *const *root, FILE *fp, unsigned f,
118 int blkht, void *arg)
120 /* Examine a red-black tree, checking that it satisfies all of the
121 * necessary invariants. If BLKHT is not equal to -1, then check that the
122 * tree's black-height is equal to BLKHT.
124 * This function uses the `xyla_bt_check' framework; see the description of
125 * that function for details. Returns `XYLA_RC_OK' on success,
126 * `XYLA_RC_BAD' if problems are found, or some other code if verification
127 * had to finish prematurely.
133 return (xyla_bt_check(cls, root, fp, f,
134 chkrb, sizeof(struct nodeinfo), &st, arg));
137 /*----- That's all, folks -------------------------------------------------*/