算法之——并查集

欢迎收看今天的算法课堂,今天的主要内容有 并 查 集并 查 集并 查 集

首先是并查集所能解决的主要问题——连接问题和路径问题,其思想是将所相连的点连成树,用一个数组记录每一个节点的前驱,如果是单个的点,前驱就是自己,方便并查的操作

并查集主要是两种操作,(union)和(find)

  1. union & find
    并主要是指将两个节点连接在一起或是将两棵树连接在一起,如果是单个的节点与一棵树或是一个节点连接,直接改变这个节点的前驱标记即可,如果是两棵树相连,那么需要遍历到树的根再进行连接——尽量减少树的深度,方便树的遍历

    具体方法如下——

int find_root(int p)
{
    //查找根节点
    while(p != parent[p])
        p = parent[p];
    return p;
}

bool isConnected(int a, int b)
{
	//判断ab节点是否相连
    return find_root(a) == find_root(b);
}

void unionElements(int a, int b)
{
    int roota = find_root(a),rootb = find_root(b);
    if(roota==rootb)	return;
    
    parent[roota] = rootb;
}
  1. 并查集的优化
    优化的角度从减少树的高度的角度进行,假如我们一直将层数高的树和一棵层数底的树进行union,那么最终的树的高度会不断增加,不过在实际操作中,由于求树的层数要用dfs较为耗时,所以经常采用每棵树元素的个数进行比较,将元素少的树加在元素多的树上
    所以在代码的层面上,只需多一步求每棵树元素的个数——
void unionElements(int a, int b)
{
    int roota = find_root(a),rootb = find_root(b);
    //遍历一遍各个节点的根节点看哪棵树的元素多
    int sz_a=0,sz_b=0;
    for(int i=0; i<cnt; i++)
    {
        find_root(i);
        if(i==roota)
            sz_a++;
        if(i==rootb)
            sz_b++;
    }
    if(roota==rootb)
        return;
    if(sz_a>sz_b)
        parent[rootb] = roota;
    else
        parent[roota] = rootb;
}
  1. 并查集的路径压缩
    在这里插入图片描述
    在求4的根节点的时候,就可以采取parent[p] = parent[parent[p]],这样就跳过了一步,那么如果提前到了根节点咋整呢?由于并查集中开始时本身的parent[p] = p,所以就会在原地打转,不影响
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值