ref:http://en.literateprograms.org/Disjoint_set_data_structure_(C)
The three main operations in disjoint set are:
MakeSet: Create a new partition containing a single given element.
Find: Figure out which partition a given element is in.
Union: Merge two partitions into a single partition.
The most efficient known and most commonly used is disjoint set forests
with path compression and the union rank heuristic
#include
<
iostream
>
#include < cstdlib >
#include < cassert >
using namespace std;
// forest node
typedef struct forest_node_t ... {
void* value;
struct forest_node_t* parent;
int rank;
} forest_node;
forest_node * MakeSet( void * value);
forest_node * Find(forest_node * node);
void Union(forest_node * node1, forest_node * node2);
// find operation
forest_node * Find(forest_node * node) ... {
forest_node* temp;
/**//* Find the root */
forest_node* root = node;
while (root->parent != NULL) ...{
root = root->parent;
}
/**//* Update the parent pointers */
while (node->parent != NULL) ...{
temp = node->parent;
node->parent = temp;
node = temp;
}
return root;
}
// union operation
/**/ /* Given the root elements of two trees, merge the trees into one tree */
/**/ /*
If rank(s) ≠ rank(t), then rank(Union(s,t)) is the larger of rank(s) and rank(t),
we attach the tree with smaller rank to the root of the tree with larger rank.
If rank(s) = rank(t), then rank(Union(s,t)) = rank(s) + 1 = rank(t) + 1.
*/
void Union(forest_node * node1, forest_node * node2) ... {
if (node1->rank > node2->rank) ...{
node2->parent = node1;
} else if (node2->rank > node1->rank) ...{
node1->parent = node2;
} else ...{ /**//* they are equal */
node2->parent = node1;
node1->rank++;
}
}
// Make-Set operation
forest_node * MakeSet( void * value) ... {
forest_node* node = (forest_node*)malloc(sizeof(forest_node));
node->value = value;
node->parent = NULL;
/**//*MakeSet always produces a tree of rank 0: */
node->rank = 0;
return node;
}
int main() ... {
int i1=1, i2=2, i3=3;
forest_node *s1=MakeSet(&i1), *s2=MakeSet(&i2), *s3=MakeSet(&i3);
assert(Find(s1) == s1);
Union(s1, s2);
assert(Find(s1) == Find(s2));
assert(Find(s1) != Find(s3));
Union(s2, s3);
assert(Find(s1) == Find(s2) &&
Find(s1) == Find(s3));
return 0;
}
#include < cstdlib >
#include < cassert >
using namespace std;
// forest node
typedef struct forest_node_t ... {
void* value;
struct forest_node_t* parent;
int rank;
} forest_node;
forest_node * MakeSet( void * value);
forest_node * Find(forest_node * node);
void Union(forest_node * node1, forest_node * node2);
// find operation
forest_node * Find(forest_node * node) ... {
forest_node* temp;
/**//* Find the root */
forest_node* root = node;
while (root->parent != NULL) ...{
root = root->parent;
}
/**//* Update the parent pointers */
while (node->parent != NULL) ...{
temp = node->parent;
node->parent = temp;
node = temp;
}
return root;
}
// union operation
/**/ /* Given the root elements of two trees, merge the trees into one tree */
/**/ /*
If rank(s) ≠ rank(t), then rank(Union(s,t)) is the larger of rank(s) and rank(t),
we attach the tree with smaller rank to the root of the tree with larger rank.
If rank(s) = rank(t), then rank(Union(s,t)) = rank(s) + 1 = rank(t) + 1.
*/
void Union(forest_node * node1, forest_node * node2) ... {
if (node1->rank > node2->rank) ...{
node2->parent = node1;
} else if (node2->rank > node1->rank) ...{
node1->parent = node2;
} else ...{ /**//* they are equal */
node2->parent = node1;
node1->rank++;
}
}
// Make-Set operation
forest_node * MakeSet( void * value) ... {
forest_node* node = (forest_node*)malloc(sizeof(forest_node));
node->value = value;
node->parent = NULL;
/**//*MakeSet always produces a tree of rank 0: */
node->rank = 0;
return node;
}
int main() ... {
int i1=1, i2=2, i3=3;
forest_node *s1=MakeSet(&i1), *s2=MakeSet(&i2), *s3=MakeSet(&i3);
assert(Find(s1) == s1);
Union(s1, s2);
assert(Find(s1) == Find(s2));
assert(Find(s1) != Find(s3));
Union(s2, s3);
assert(Find(s1) == Find(s2) &&
Find(s1) == Find(s3));
return 0;
}