static void tree_to_vine (struct rtbst_table *tree) { struct rtbst_node *p; if (tree->rtbst_root == NULL) return; p = tree->rtbst_root; while (p->rtbst_link[0] != NULL) p = p->rtbst_link[0]; for (;;) { struct rtbst_node *q = p->rtbst_link[1]; if (p->rtbst_rtag == RTBST_CHILD) { while (q->rtbst_link[0] != NULL) q = q->rtbst_link[0]; p->rtbst_rtag = RTBST_THREAD; p->rtbst_link[1] = q; } if (q == NULL) break; q->rtbst_link[0] = p; p = q; } tree->rtbst_root = p; } /* Performs a compression transformation |count| times, starting at |root|. */ static void compress (struct rtbst_node *root, unsigned long nonthread, unsigned long thread) { assert (root != NULL); while (nonthread--) { struct rtbst_node *red = root->rtbst_link[0]; struct rtbst_node *black = red->rtbst_link[0]; root->rtbst_link[0] = black; red->rtbst_link[0] = black->rtbst_link[1]; black->rtbst_link[1] = red; root = black; } while (thread--) { struct rtbst_node *red = root->rtbst_link[0]; struct rtbst_node *black = red->rtbst_link[0]; root->rtbst_link[0] = black; red->rtbst_link[0] = NULL; black->rtbst_rtag = RTBST_CHILD; root = black; } } /* Converts |tree|, which must be in the shape of a vine, into a balanced tree. */ static void vine_to_tree (struct rtbst_table *tree) { unsigned long vine; /* Number of nodes in main vine. */ unsigned long leaves; /* Nodes in incomplete bottom level, if any. */ int height; /* Height of produced balanced tree. */ leaves = tree->rtbst_count + 1; for (;;) { unsigned long next = leaves & (leaves - 1); if (next == 0) break; leaves = next; } leaves = tree->rtbst_count + 1 - leaves; compress ((struct rtbst_node *) &tree->rtbst_root, 0, leaves); vine = tree->rtbst_count - leaves; height = 1 + (leaves > 0); if (vine > 1) { unsigned long nonleaves = vine / 2; leaves /= 2; if (leaves > nonleaves) { leaves = nonleaves; nonleaves = 0; } else nonleaves -= leaves; compress ((struct rtbst_node *) &tree->rtbst_root, leaves, nonleaves); vine /= 2; height++; } while (vine > 1) { compress ((struct rtbst_node *) &tree->rtbst_root, vine / 2, 0); vine /= 2; height++; } } /* Balances |tree|. */ void rtbst_balance (struct rtbst_table *tree) { assert (tree != NULL); tree_to_vine (tree); vine_to_tree (tree); }