231 lines
6.1 KiB
C
231 lines
6.1 KiB
C
#include <stdlib.h>
|
|
#include "rbtree.h"
|
|
|
|
// Implementation of the rbtree modeled from CLRS (3rd edition).
|
|
|
|
static struct rbnode *rbnode_first (
|
|
struct rbnode const *nil, struct rbnode *node
|
|
) {
|
|
while (node->left != nil) node = node->left;
|
|
return node;
|
|
}
|
|
|
|
struct rbnode *rbtree_first (struct rbtree const *tree) {
|
|
struct rbnode const *nil = &tree->nil;
|
|
return tree->root == nil ? NULL : rbnode_first (nil, tree->root);
|
|
}
|
|
|
|
struct rbnode *rbtree_next (struct rbtree const *tree, struct rbnode *node) {
|
|
struct rbnode const *nil = &tree->nil;
|
|
if (node->right != nil) return rbnode_first (nil, node->right);
|
|
while (1) {
|
|
if (node->parent == nil) return NULL;
|
|
if (node == node->parent->left) return node->parent;
|
|
node = node->parent;
|
|
}
|
|
}
|
|
|
|
struct rbnode *rbtree_get (struct rbtree const *tree, unsigned x) {
|
|
struct rbnode const *nil = &tree->nil;
|
|
struct rbnode *node = tree->root;
|
|
while (node != nil) {
|
|
if (node->peer == x) return node;
|
|
else node = x < node->peer ? node->left : node->right;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void rbtree_mk (struct rbtree *tree) {
|
|
tree->nil = (struct rbnode) { .parent = &tree->nil, .red = 0 };
|
|
tree->root = &tree->nil;
|
|
}
|
|
|
|
static void rbnode_clear (struct rbnode const *nil, struct rbnode *node) {
|
|
if (node == nil) return;
|
|
rbnode_clear (nil, node->left);
|
|
rbnode_clear (nil, node->right);
|
|
free (node);
|
|
}
|
|
|
|
void rbtree_clear (struct rbtree *tree) {
|
|
rbnode_clear (&tree->nil, tree->root);
|
|
tree->root = &tree->nil;
|
|
}
|
|
|
|
static void rbtree_graft (
|
|
struct rbtree *tree, struct rbnode *node, struct rbnode *bro
|
|
) {
|
|
if ((bro->parent = node->parent) == &tree->nil) tree->root = bro;
|
|
else if (node == node->parent->left) node->parent->left = bro;
|
|
else node->parent->right = bro;
|
|
}
|
|
|
|
static void rbtree_rotate (struct rbtree *tree, struct rbnode *node, int left) {
|
|
struct rbnode *bro;
|
|
if (left) {
|
|
bro = node->right;
|
|
(node->right = bro->left)->parent = node;
|
|
bro->left = node;
|
|
} else {
|
|
bro = node->left;
|
|
(node->left = bro->right)->parent = node;
|
|
bro->right = node;
|
|
}
|
|
rbtree_graft (tree, node, bro);
|
|
node->parent = bro;
|
|
}
|
|
|
|
void rbtree_add (struct rbtree *tree, struct rbnode *node) {
|
|
struct rbnode *nil = &tree->nil, *parent = nil, *tmp = tree->root, *grand;
|
|
int left = 0;
|
|
while (tmp != nil) {
|
|
parent = tmp;
|
|
left = node->peer < parent->peer;
|
|
tmp = left ? parent->left : parent->right;
|
|
}
|
|
node->red = 1;
|
|
node->left = node->right = nil;
|
|
if ((node->parent = parent) == nil) tree->root = node;
|
|
else if (left) parent->left = node;
|
|
else parent->right = node;
|
|
|
|
while (parent->red) {
|
|
left = parent == (grand = parent->parent)->left;
|
|
tmp = left ? grand->right : grand->left;
|
|
if (tmp->red) {
|
|
parent->red = tmp->red = 0; grand->red = 1;
|
|
parent = (node = grand)->parent;
|
|
} else {
|
|
if (node == (left ? parent->right : parent->left)) {
|
|
rbtree_rotate (tree, parent, left);
|
|
tmp = parent; parent = node; node = tmp;
|
|
}
|
|
parent->red = 0; grand->red = 1;
|
|
rbtree_rotate (tree, grand, !left);
|
|
}
|
|
}
|
|
tree->root->red = 0;
|
|
}
|
|
|
|
void rbtree_rm (struct rbtree *tree, struct rbnode *node) {
|
|
struct rbnode *nil = &tree->nil, *orig = node, *parent, *tmp;
|
|
int rl;
|
|
if (node->left == nil) {
|
|
rbtree_graft (tree, node, node->right);
|
|
rl = node->red;
|
|
node = node->right;
|
|
} else if (node->right == nil) {
|
|
rbtree_graft (tree, node, node->left);
|
|
rl = node->red;
|
|
node = node->left;
|
|
} else {
|
|
struct rbnode *broken = (tmp = rbnode_first (nil, node->right))->right;
|
|
rl = tmp->red; tmp->red = node->red;
|
|
(tmp->left = node->left)->parent = tmp;
|
|
if ((parent = tmp->parent) == node) broken->parent = tmp;
|
|
else {
|
|
(parent->left = broken)->parent = parent;
|
|
(tmp->right = node->right)->parent = tmp;
|
|
}
|
|
rbtree_graft (tree, node, tmp);
|
|
node = broken;
|
|
}
|
|
if (rl) goto retn;
|
|
|
|
while (!((parent = node->parent) == nil || node->red)) {
|
|
rl = node == parent->left;
|
|
tmp = rl ? parent->right : parent->left;
|
|
if (tmp->red) {
|
|
tmp->red = 0; parent->red = 1;
|
|
tmp = rl ? tmp->left : tmp->right;
|
|
rbtree_rotate (tree, parent, rl);
|
|
}
|
|
if (!(tmp->left->red || tmp->right->red)) {
|
|
tmp->red = 1;
|
|
node = parent;
|
|
} else {
|
|
if (!(rl ? tmp->right : tmp->left)->red) {
|
|
struct rbnode *child = rl ? tmp->left : tmp->right;
|
|
child->red = 0; tmp->red = 1;
|
|
rbtree_rotate (tree, tmp, !rl);
|
|
tmp = child;
|
|
}
|
|
tmp->red = parent->red;
|
|
(rl ? tmp->right : tmp->left)->red = parent->red = 0;
|
|
rbtree_rotate (tree, parent, rl);
|
|
node = tree->root;
|
|
}
|
|
}
|
|
node->red = 0;
|
|
|
|
retn:
|
|
free (orig);
|
|
}
|
|
|
|
int rbforest_mk (struct rbforest *forest, unsigned n) {
|
|
if (!(forest->trees = malloc (n * sizeof (struct rbtree)))) return 0;
|
|
for (unsigned i = 0; i < n; ++i) rbtree_mk (forest->trees + i);
|
|
forest->score = 0;
|
|
forest->cnt = 0;
|
|
forest->n = n;
|
|
return 1;
|
|
}
|
|
|
|
void rbforest_fin (struct rbforest *forest) {
|
|
for (unsigned i = 0; i < forest->n; ++i) rbtree_clear (forest->trees + i);
|
|
free (forest->trees);
|
|
forest->trees = NULL;
|
|
forest->cnt = 0;
|
|
forest->score = 0;
|
|
}
|
|
|
|
int rbforest_add (
|
|
struct rbforest *forest, unsigned x1, unsigned x2, signed score
|
|
) {
|
|
struct rbnode *node1, *node2;
|
|
if (!(node1 = malloc (sizeof (struct rbnode)))) goto node1_err;
|
|
if (!(node2 = malloc (sizeof (struct rbnode)))) goto node2_err;
|
|
|
|
node1->peer = x2;
|
|
node2->peer = x1;
|
|
node1->cross = node2;
|
|
node2->cross = node1;
|
|
node1->score = node2->score = score;
|
|
rbtree_add (forest->trees + x1, node1);
|
|
rbtree_add (forest->trees + x2, node2);
|
|
forest->score += score;
|
|
--forest->cnt;
|
|
|
|
return 1; node2_err:
|
|
free (node1); node1_err:
|
|
return 0;
|
|
}
|
|
|
|
void rbforest_rm (struct rbforest *forest, unsigned x) {
|
|
struct rbtree *tree = forest->trees + x;
|
|
for (
|
|
struct rbnode *node = rbtree_first (tree);
|
|
node; node = rbtree_next (tree, node)
|
|
) {
|
|
rbtree_rm (forest->trees + node->peer, node->cross);
|
|
forest->score -= node->score;
|
|
--forest->cnt;
|
|
}
|
|
rbtree_clear (tree);
|
|
}
|
|
|
|
void rbforest_pairs (struct rbforest const *forest, unsigned pairs[][2]) {
|
|
struct rbtree *tree = forest->trees;
|
|
unsigned idx = 0;
|
|
for (unsigned i = 1; i < forest->n; ++i, ++tree) {
|
|
for (
|
|
struct rbnode *node = rbtree_first (tree);
|
|
node && node->peer < i; node = rbtree_next (tree, node)
|
|
) {
|
|
pairs[idx][0] = i;
|
|
pairs[idx++][1] = node->peer;
|
|
}
|
|
}
|
|
}
|
|
|