disjoint set (union-find set) (并查集)

 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;
}


你可能感兴趣的:(disjoint set (union-find set) (并查集))