算法合集——并查集union-find

        并查集算法主要分为quic-find, quick-union以及union-find方法。但出于效率考虑,一般使用union-find算法进行实际操作。

        union-find算法的思想就是利用一个数组id[]记录每个节点的父节点,例如现要将节点1(id[1] = 1)连接到节点2(id[2] = 2),则令id[1] = 2即可;同时,若节点为根节点,则令其id值等于其自身。通过这种方式,可将序列转化为由许多树组成的森林,若要判断两节点是否连通,只需比较二者根节点是否相同即可。

        但为了进一步算法效率,我们还可以再创建一个数组sz[]来记录每棵树的大小,使得在将两棵树归并时只会将小树连接到大树上,从而尽可能减小最终结果中树的高度,进一步优化算法。

        以下就是我用c++实现的union-find的代码:

#ifndef UNION_FIND_H
#define UNION_FIND_H


class union_find
{
private:
    int id[];      //记录每个节点的父节点,根节点处为其自身
    int sz[];      //记录节点处树的大小
    int num;       //记录总的联通分量数

public:
    union_find(int N);
    ~union_find() {delete [] id; delete [] sz;};
    int _num() {return num;};
    bool connected(int p, int q) {return _find(p) == _find(q);};  //判断是否联通
    int _find(int p);                                             //寻找根节点
    void _union(int p, int q);                                    //连接两棵树
};

#endif 

#include "union_find.h"

union_find::union_find(int N)
{
    num = N;
    for(int i; i < N; i++)
    {
        id[i] = i;
        sz[i] = 1;
    }
}

int union_find::_find(int p)
{
    while(p != id[p])             //寻找p的根节点
        p = id[p];
    return p;
}

void union_find::_union(int p, int q)
{
    int proot = _find(p);
    int qroot = _find(q);
    if(proot != qroot)                        //判断两节点是否是联通的
    {
        if(sz[proot] < sz[qroot])             //判断树的大小
        {
            id[proot] = qroot;                //小树的根节点接到大树根节点上
            sz[qroot] += sz[proot];           //大树的元素数量等于其自加小树的节点数
        }
        else
        {
            id[qroot] = proot;
            sz[proot] += sz[qroot];
        }
    }
    num--;                                    //分量数减一
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值