数据结构复习:并查集基本操作实现

#include <stdio.h>
//并查集操作实现(顺序存储,双亲表示法实现)
//并查集的操作主要有两个
//1)查找某个元素属于哪个集合
//2)合并两个集合
#define MAX_SIZE  100

typedef struct ElemType {
    char value;
} ElemType;
typedef struct {
    ElemType data;
    int parent;
} Node;
typedef struct {
    Node sets[MAX_SIZE];
    int n;
} UFSets;

//初始化
void Initial(UFSets &S, int size) {
    for (int i = 0; i < size; ++i) {
        S.sets[i].data = {};
        S.sets[i].parent = -1;
    }
    S.n = size;
}


查找某个元素的属于哪个集合
//Node Find(Node S[], Node x) {
//    if (x.parent == -1)
//        return x;
//    while (x.parent != -1) {
//        x = S[x.parent];
//    }
//    return x;
//}

合并两个结合
//void Union(UFSets &S, int index1, int index2) {
//    Node &root1 = S.sets[index1];
//    Node &root2 = S.sets[index2];
//    if(root1.parent != -1 ||
//    root2.parent!=-1) {//不是集合
//        return;
//    }
//    if (root1.data.value == root2.data.value
//        && root1.parent == root2.parent) {//相同的集合
//        return;
//    } else {
//        root2.parent = index1;
//    }
//}

//并操作的优化:小树合并到大树
//该方法构造的树高不超过 log2(n)下取整 +1
void Union(UFSets &S, int index1, int index2) {
    Node &root1 = S.sets[index1];
    Node &root2 = S.sets[index2];
    if (root1.parent >= 0 ||
        root2.parent >= 0) {//不是集合
        return;
    }
    if (root1.data.value == root2.data.value
        && root1.parent == root2.parent) {//相同的集合
        return;
    } else {
        //小树合并到大树
        if (root1.parent >= root2.parent) {
            root2.parent += root1.parent;
            root1.parent = index2;
        } else {
            root1.parent += root2.parent;
            root2.parent = index1;
        }

    }
}


查找某个元素的属于哪个集合
通过小树合并大树的操作,查找最坏时间复杂度log2(n)
//Node Find(Node S[], Node x) {
//    if (x.parent <0)
//        return x;
//    while (x.parent >=0) {
//        x = S[x.parent];
//    }
//    return x;
//}
//查找某个元素的属于哪个集合 路径压缩优化,即某次查找把所有查找到的元素挂到根元素下面
Node Find(UFSets &S, int i) {
    Node x = S.sets[i];
    //循环找到根
    if (x.parent < 0)
        return x;
    Node root = x;
    int rootIndex = 0;
    while (root.parent >= 0) {
        rootIndex = root.parent;
        root = S.sets[root.parent];
    }
    while (x.parent >= 0) {
        S.sets[i].parent = rootIndex;//已经访问的元素挂到根元素下面
        i = x.parent;
        x = S.sets[i];
    }
    return root;
}

int main() {

    UFSets S;

    Initial(S, 13);
    //添加一些元素

    //创建集合 A
    Node A, B, C, D, E, F, G, H, I, J, K, L, M;
    A.parent = -6;
    C.parent = -2;
    D.parent = -5;

    A.data = {'A'};
    S.sets[0] = A;


    B.data = {'B'};
    B.parent = 0;
    S.sets[1] = B;


    //创建集合 C
    C.data = {'C'};

    S.sets[2] = C;

    //创建集合 D
    D.data = {'D'};
    S.sets[3] = D;


    E.data = {'E'};
    E.parent = 1;
    S.sets[4] = E;
    F.data = {'F'};
    F.parent = 1;
    S.sets[5] = F;


    G.data = {'G'};
    G.parent = 2;
    S.sets[6] = G;


    H.data = {'H'};
    H.parent = 3;
    S.sets[7] = H;
    I.data = {'I'};
    I.parent = 3;
    S.sets[8] = I;
    J.data = {'J'};
    J.parent = 3;
    S.sets[9] = J;


    K.data = {'K'};
    K.parent = 4;
    S.sets[10] = K;
    L.data = {'L'};
    L.parent = 4;
    S.sets[11] = L;


    M.data = {'M'};
    M.parent = 7;
    S.sets[12] = M;

    Node X = M;
    int index = 11;
    
    //查找 M
    Node Y = Find(S, index);
    printf("%c属于集合%c\n", X.data.value, Y.data.value);

	//合并 A C两个集合
    Union(S, 0, 3);

    
    // 查找 M
    Y = Find(S, index);
    printf("%c属于集合%c\n", X.data.value, Y.data.value);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值