并查集的查与并(路径压缩)(递归及非递归)

注意:

1、集合从下标为0开始
2、初始化为-1
3、数组元素存的值是父节点的元素
4、根节点存储当前树的大小,本应该为-1,现在为 负节点数目

路径压缩:即每找一次就会将当前节点到根节点途中的所有节点都指向根节点,使下一次查找越来越容易;

集合合并:将小集合合并到大集合,可以保证树的平衡性;便于操作

#include 
#include 
#include 
#include 
#include 

using namespace std;

const int MAX = 100;

int S[MAX];

//初始化
void InitSet()
{
    memset(S, -1, sizeof(S));
}

//递归 路径压缩
int FindSet1(int X)
{
    if(S[X] < 0)        //若找到根节点返回当前元素值作为集合名称
        return X;
    else                //每找一次就会将当前节点到根节点途中的所有节点都指向根节点
        return S[X] = FindSet1(S[X]);
}

//非递归 路径压缩
//每找一次就会将当前节点指向根节点
int FindSet2(int X)
{
    if(S[X] < 0)
        return X;
    int R = X;
    while(S[S[X]] >= 0)
    {
        R = S[X];
        S[X] = S[R];
    }
    return S[X];
}


//小集合并入大集合
void UnionSet(int X, int Y)
{
    int Root1 = FindSet1(X);
    int Root2 = FindSet1(Y);

    //同一棵树
    if(Root1 == Root2) return;

    //根节点为负值,即集合2大
    if(S[Root2] < S[Root1])
    {
        //根节点累加集合小的节点数,为负数
        S[Root2] += S[Root1];
        //小集合根节点指向大集合
        S[Root1] = Root2;
    }
    else
    {
        S[Root1] += S[Root2];
        S[Root2] = Root1;
    }
}

int main()
{
    InitSet();

    for(int i = 0; i < 5; i++)
    {
        int x, y;
        cin >> x >> y;
        UnionSet(x, y);
    }

    cout << FindSet1(5) <<endl;
    return 0;
}

你可能感兴趣的:(算法与数据结构)