并查集——启发式合并,路径压缩

一直没想过自己写的并查集的复杂度= =。。。看那一行代码还挺窃喜——贴一下正版的启发式合并,这样复杂度就真正到了反阿克曼函数那什么balabala


一个优化是:把小的树合并到大树中,这样会让深度不太大。这个优化称为启发式合并。

一个优化是把沿途上所有结点的父亲改成根。这一步是顺便的,不增加时间复杂度,却使得今后的操作比较快。这个优化称为路径压缩
用 p[i] 表示 i 的父亲,而 rank[i] 表示 i 的秩,并用秩来代替深度做刚才提到的启发式合并。

void makeset ( int x ){
    rank [ x ] = 0;
    p[x] = x;
}
int findset ( int x )
{
    int px = x , i ;
    while ( px != p [ px ]) px = p [ px ]; // find root
    while ( x != px ) // path compression
    {
        i = p [ x ];
        p [ x ] = px ;
        x = i;
    }
    return px ;
}
void unionset ( int x , int y )
{
    x = findset ( x );
    y = findset ( y );
    if ( rank [ x ] > rank [ y ]) p [ y ] = x ;
    else{
        p[x ] = y;
        if ( rank [ x ] == rank [ y ]) rank [ y ]++;
    }    
}



posted @ 2016-02-03 15:42  YCuangWhen  阅读(907)  评论(0编辑  收藏  举报