并查集:连通性问题

树的应用——使用并查集解决动态连通性问题(下篇:加权的快速合并) 上篇:树的应用——使用并查集解决动态连通性问题(含C++代码实现)(上篇:快速查找) 中篇:树的应用——使用并查集解决动态连通性问题(含C++代码实现)(中篇:快速合并) 第三种设计:加权快速合并 Weighting-Quick-union 在(中篇:快速合并)中,我们知道,快速合并算法无论是查找还是合并,主要的时间消耗在于回溯根。如果树很深,那么回溯将会消耗大量的时间。因此,改进本算法的方向就是:使树的深度尽量小(尽量平坦),这样子无论是从哪个节点回溯到根都很快。 从上图我们可以直观感受到,右边树结构 阅读详情

并查集:连通性问题

1. 为什么需要并查集

假设你刷朋友圈,看到 A 点赞了 B,B 评论了 C,C 转发了 D。直觉告诉你——A、B、C、D 在一个圈子里。判断"两个人是否在同一个圈子",就是连通性问题。

并查集(Union-Find / Disjoint Set Union)专门解决这类问题,支持两个操作:

  • Union(x, y):把 x 和 y 所在的集合合并
  • Find(x):找出 x 所属的集合的代表元素

2. Quick-Find:暴力连通

最朴素的想法:给每个元素一个"组号",同组元素编号相同。

#include <vector>
#include <iostream>

class QuickFind {
    std::vector<int> id;  // 组号
public:
    QuickFind(int n) : id(n) {
        for (int i = 0; i < n; ++i)
            id[i] = i;          // 初始化:每个人自成一组
    }

    bool connected(int p, int q) {
        return id[p] == id[q];   // O(1) 判断连通
    }

    void unite(int p, int q) {   // union 是关键字,用 unite
        int pid = id[p];
        int qid = id[q];
        if (pid == qid) return;
        for (int i = 0; i < id.size(); ++i)
            if (id[i] == pid)    // 遍历所有元素,改组号
                id[i] = qid;     // O(n)
    }
};

问题:union 操作要遍历整个数组,O(n)。n 一大的数据场景直接崩溃。

3. Quick-Union:树形结构

把"组"换成"树"——每个元素只存自己的父节点,根节点代表整个集合。

#include <vector>

class QuickUnion {
    std::vector<int> parent;
public:
    QuickUnion(int n) : parent(n) {
        for (int i = 0; i < n; ++i)
            parent[i] = i;
    }

    int find(int x) {
        while (parent[x] != x)
            x = parent[x];       // 沿着父指针向上找根
        return x;
    }

    bool connected(int p, int q) {
        return find(p) == find(q);
    }

    void unite(int p, int q) {
        int rootP = find(p);
        int rootQ = find(q);
        if (rootP == rootQ) return;
        parent[rootP] = rootQ;   // 一棵树挂到另一棵树根
    }
};

问题:树可能退化成链表。1→2→3→4→5,find(5) 要走 5 步,union 也是 O(n)。

Quick-Union + 路径压缩

1

2

3

4

5

find(5) 走 4 步找到根,路径压缩把沿途节点直接指向根:

5

4

3

2

1

压缩后结构:

2

1

3

4

5

所有节点直接指向根,下次 find 就是 O(1)。

4. 按秩合并

光压缩还不够——如果 union 时总是把大树挂到小树上,树还是会变高。按秩合并(Union by Rank):记录每棵树的高度(秩),把矮树挂到高树下。

#include <vector>

class UnionFind {
    std::vector<int> parent;
    std::vector<int> rank;   // 树的高度上界

public:
    UnionFind(int n) : parent(n), rank(n, 0) {
        for (int i = 0; i < n; ++i)
            parent[i] = i;
    }

    int find(int x) {
        if (parent[x] != x)
            parent[x] = find(parent[x]);  // 路径压缩
        return parent[x];
    }

    void unite(int x, int y) {
        int rx = find(x), ry = find(y);
        if (rx == ry) return;
        if (rank[rx] < rank[ry]) {
            parent[rx] = ry;
        } else if (rank[rx] > rank[ry]) {
            parent[ry] = rx;
        } else {
            parent[ry] = rx;      // 同高度,选一个做根
            ++rank[rx];           // 高度 +1
        }
    }

    bool connected(int x, int y) {
        return find(x) == find(y);
    }
};

5. 复杂度

方法unionfind最坏
Quick-FindO(n)O(1)O(n²)
Quick-UnionO(n)O(n)O(n²)
路径压缩几乎 O(1)几乎 O(1)O(log n)
按秩合并O(log n)O(log n)O(log n)
路径压缩 + 按秩合并α(n)α(n)α(n)

α(n) 是反阿克曼函数。对于 n ≤ 10⁸⁰,α(n) ≤ 4。所以实际复杂度是常数。

6. 基础模板(面试通用)

#include <vector>

class UnionFind {
    std::vector<int> parent;
    std::vector<int> rank;
    int count;                  // 连通分量数

public:
    UnionFind(int n) : parent(n), rank(n, 0), count(n) {
        for (int i = 0; i < n; ++i)
            parent[i] = i;
    }

    int find(int x) {
        if (parent[x] != x)
            parent[x] = find(parent[x]);
        return parent[x];
    }

    void unite(int x, int y) {
        int rx = find(x), ry = find(y);
        if (rx == ry) return;
        if (rank[rx] < rank[ry]) {
            parent[rx] = ry;
        } else if (rank[rx] > rank[ry]) {
            parent[ry] = rx;
        } else {
            parent[ry] = rx;
            ++rank[rx];
        }
        --count;
    }

    int getCount() const { return count; }
};

7. 面试题

7.1 岛屿数量

题目:'1' 是陆地,'0' 是水,求岛屿数。

思路:每个 '1' 是一个节点,相邻的 '1' 合并。最后统计有多少个集合。

#include <vector>

class UnionFind {
    std::vector<int> parent, rank;
    int count;
public:
    UnionFind(int n) : parent(n), rank(n, 0), count(n) {
        for (int i = 0; i < n; ++i) parent[i] = i;
    }
    int find(int x) {
        if (parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }
    void unite(int x, int y) {
        int rx = find(x), ry = find(y);
        if (rx == ry) return;
        if (rank[rx] < rank[ry])      parent[rx] = ry;
        else if (rank[rx] > rank[ry]) parent[ry] = rx;
        else { parent[ry] = rx; ++rank[rx]; }
        --count;
    }
    int getCount() const { return count; }
};

class Solution {
public:
    int numIslands(std::vector<std::vector<char>>& grid) {
        if (grid.empty() || grid[0].empty()) return 0;
        int m = grid.size(), n = grid[0].size();
        UnionFind uf(m * n);
        int water = 0;
        auto id = [n](int r, int c) { return r * n + c; };

        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == '0') { ++water; continue; }
                if (i > 0 && grid[i - 1][j] == '1')
                    uf.unite(id(i, j), id(i - 1, j));
                if (j > 0 && grid[i][j - 1] == '1')
                    uf.unite(id(i, j), id(i, j - 1));
            }
        }
        return uf.getCount() - water;
    }
};

7.2 朋友圈 / 省份数量

题目:isConnected[i][j] = 1 表示 i 和 j 直接相连,求省份数。

#include <vector>

class UnionFind {
    std::vector<int> parent, rank;
    int count;
public:
    UnionFind(int n) : parent(n), rank(n, 0), count(n) {
        for (int i = 0; i < n; ++i) parent[i] = i;
    }
    int find(int x) {
        if (parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }
    void unite(int x, int y) {
        int rx = find(x), ry = find(y);
        if (rx == ry) return;
        if (rank[rx] < rank[ry])      parent[rx] = ry;
        else if (rank[rx] > rank[ry]) parent[ry] = rx;
        else { parent[ry] = rx; ++rank[rx]; }
        --count;
    }
    int getCount() const { return count; }
};

class Solution {
public:
    int findCircleNum(std::vector<std::vector<int>>& isConnected) {
        int n = isConnected.size();
        UnionFind uf(n);
        for (int i = 0; i < n; ++i)
            for (int j = i + 1; j < n; ++j)
                if (isConnected[i][j])
                    uf.unite(i, j);
        return uf.getCount();
    }
};

7.3 冗余连接

题目:n 个节点 n 条边的无向图,删掉一条边使其变成树。返回那条多余边。

#include <vector>

class UnionFind {
    std::vector<int> parent, rank;
public:
    UnionFind(int n) : parent(n), rank(n, 0) {
        for (int i = 0; i < n; ++i) parent[i] = i;
    }
    int find(int x) {
        if (parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }
    bool unite(int x, int y) {
        int rx = find(x), ry = find(y);
        if (rx == ry) return false;  // 已经在同集合 → 形成环
        if (rank[rx] < rank[ry])      parent[rx] = ry;
        else if (rank[rx] > rank[ry]) parent[ry] = rx;
        else { parent[ry] = rx; ++rank[rx]; }
        return true;
    }
};

class Solution {
public:
    std::vector<int> findRedundantConnection(
            std::vector<std::vector<int>>& edges) {
        int n = edges.size();
        UnionFind uf(n + 1);
        for (auto& e : edges) {
            if (!uf.unite(e[0], e[1]))
                return {e[0], e[1]};
        }
        return {};
    }
};

解释:树有 n 个节点、n−1 条边。多出一条边后,遍历所有边,当发现两个节点已经连通时,这条边就是冗余的——它形成了环。

7.4 最长连续序列

题目:无序数组 [100, 4, 200, 1, 3, 2],最长连续序列 [1,2,3,4] 长度为 4。

并查集解法:连续的数合并,统计最大集合大小。

#include <vector>
#include <unordered_map>
#include <algorithm>

class UnionFind {
    std::vector<int> parent, rank, size;
public:
    UnionFind(int n) : parent(n), rank(n, 0), size(n, 1) {
        for (int i = 0; i < n; ++i) parent[i] = i;
    }
    int find(int x) {
        if (parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }
    int unite(int x, int y) {
        int rx = find(x), ry = find(y);
        if (rx == ry) return size[rx];
        if (rank[rx] < rank[ry]) {
            parent[rx] = ry;
            size[ry] += size[rx];
            return size[ry];
        } else if (rank[rx] > rank[ry]) {
            parent[ry] = rx;
            size[rx] += size[ry];
            return size[rx];
        } else {
            parent[ry] = rx;
            size[rx] += size[ry];
            ++rank[rx];
            return size[rx];
        }
    }
};

class Solution {
public:
    int longestConsecutive(std::vector<int>& nums) {
        if (nums.empty()) return 0;
        int n = nums.size();
        UnionFind uf(n);
        std::unordered_map<int, int> valToIdx;
        int ans = 1;
        for (int i = 0; i < n; ++i) {
            if (valToIdx.count(nums[i])) continue;
            valToIdx[nums[i]] = i;
            if (valToIdx.count(nums[i] - 1))
                ans = std::max(ans, uf.unite(i, valToIdx[nums[i] - 1]));
            if (valToIdx.count(nums[i] + 1))
                ans = std::max(ans, uf.unite(i, valToIdx[nums[i] + 1]));
        }
        return ans;
    }
};

对比哈希解法:哈希法(存端点)O(n) 时间 O(n) 空间,代码更短。并查集解法思路更直观——连续的数天然"连通",但常数更大。面试中哈希法更推荐,但掌握并查集解法体现你举一反三的能力。

7.5 连通网络的操作次数

题目:n 台电脑,用网线 connections[i] = [a, b] 连接。求最少移动网线次数使所有电脑连通。

#include <vector>

class UnionFind {
    std::vector<int> parent, rank;
    int count;
public:
    UnionFind(int n) : parent(n), rank(n, 0), count(n) {
        for (int i = 0; i < n; ++i) parent[i] = i;
    }
    int find(int x) {
        if (parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }
    bool unite(int x, int y) {
        int rx = find(x), ry = find(y);
        if (rx == ry) return false;
        if (rank[rx] < rank[ry])      parent[rx] = ry;
        else if (rank[rx] > rank[ry]) parent[ry] = rx;
        else { parent[ry] = rx; ++rank[rx]; }
        --count;
        return true;
    }
    int getCount() const { return count; }
};

class Solution {
public:
    int makeConnected(int n, std::vector<std::vector<int>>& connections) {
        if (connections.size() < n - 1) return -1;  // 线不够
        UnionFind uf(n);
        int extra = 0;
        for (auto& c : connections)
            if (!uf.unite(c[0], c[1])) ++extra;
        int need = uf.getCount() - 1;   // 连通分量数 - 1
        return need <= extra ? need : -1;
    }
};

解释:n 台电脑连通至少需要 n−1 条线。多余的线可以移动。统计多余线和孤立分量数即可。

7.6 等式方程的可满足性

题目:给定 ["a==b","b!=c","c==a"],判断是否矛盾。

#include <vector>
#include <string>

class UnionFind {
    std::vector<int> parent, rank;
public:
    UnionFind(int n) : parent(n), rank(n, 0) {
        for (int i = 0; i < n; ++i) parent[i] = i;
    }
    int find(int x) {
        if (parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }
    void unite(int x, int y) {
        int rx = find(x), ry = find(y);
        if (rx == ry) return;
        if (rank[rx] < rank[ry])      parent[rx] = ry;
        else if (rank[rx] > rank[ry]) parent[ry] = rx;
        else { parent[ry] = rx; ++rank[rx]; }
    }
    bool connected(int x, int y) { return find(x) == find(y); }
};

class Solution {
public:
    bool equationsPossible(std::vector<std::string>& equations) {
        UnionFind uf(26);  // 只有小写字母
        // 第一遍:处理所有 ==
        for (auto& eq : equations)
            if (eq[1] == '=')
                uf.unite(eq[0] - 'a', eq[3] - 'a');
        // 第二遍:检查 != 是否矛盾
        for (auto& eq : equations)
            if (eq[1] == '!' && uf.connected(eq[0] - 'a', eq[3] - 'a'))
                return false;
        return true;
    }
};

解释:先用 == 建立连通关系,再用 != 检查是否两个本应不同的变量已经被连通。若连通则矛盾。

8. 总结

并查集是少数能在教科书和面试题中保持完全一致实现的数据结构。背下模板,面试遇到"连通"、“集合”、“分组”、"检测环"这类关键词,直接套用。

关键记忆点:

  • 路径压缩:find 时顺手把沿途节点挂到根上
  • 按秩合并:矮树挂高树,避免树退化
  • count 变量:用来统计连通分量数,很多题目直接返回这个值

反阿克曼函数的常数极小,可以用一辈子的数据结构。

并查集算法精讲:从亲戚问题到动态连通性高效解决方案 在计算机科学中,处理元素间的动态连通性查询是一类基础且重要的问题,其核心在于高效判断两个元素是否属于同一集合。并查集(Union-Find Set)正是为此设计的经典数据结构,它通过维护每个元素的“代表元”来组织集合关系。其原理基于森林表示法,每个集合对应一棵树,树根即为代表元。通过“查找”与“合并”两大核心操作,并查集能够以接近常数级的均摊时间复杂度处理连通性查询,这得益于路径压缩和按秩合并等关键优化技术。这种高效性使其在需要频繁判断元素分组关系的场景中具有极高的技术价值,例如社交网络中的好友关系判断、网 阅读详情

相关推荐

并查集:连通性问题的终极利器

并查集:高效解决连通性问题的数据结构 并查集是一种处理不相交集合合并与查询问题的树型数据结构,核心操作包括Union(合并集合)和Find(查询所属集合)。通过路径压缩和按秩合并两种优化技术,可将时间复杂度从O(n)降至接近O(1)的α(n)(反阿克曼函数)。该算法广泛应用于社交网络分析、迷宫生成、电路设计等领域,能高效处理百万级甚至亿级的动态连通性问题。在社交网络场景中,相比传统DFS/BFS,并查集无需构建完整图即可实现毫秒级的朋友圈关系计算。其分布式实现还可扩展至工业级应用,如Facebook使用分层

JDT的专栏 1092

解决连通性问题的利器:并查集

1)并查集是解决连通性问题的最佳利器,要熟练掌握并查集的原理,实现,并一定要手撕并查集代码! 2)今后在很多题目中,可能咱们不需要包装节点,因为节点已经告诉你了,你得学会内置函数修改形参,然后运用宏观调度机制,把并查集用起来,熟悉起来。 3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

weixin_46838716的博客 865

并查集: 轻松解决连通性问题

本文介绍并查集. 用图示和代码以及LeetCode例题帮助读者理解.

一些C++相关的技术笔记或者教程. 1414

并查集:连通性问题的解决方案

并查集是一种高效处理连通性问题的数据结构,支持快速查找和合并操作。本文介绍了并查集的基本概念、实现原理(包括路径压缩和按秩合并优化)及其应用场景。并查集在图算法(如Kruskal最小生成树)、图像处理(区域标记)等领域有广泛应用,其近乎常数时间的时间复杂度使其成为处理大规模连通性问题的理想选择。通过代码示例展示了并查集的具体实现和典型应用,帮助读者理解其工作原理和使用方法。

从不水文,坚持创作,加油 1411

线段树与并查集:解决复杂连通性问题

本文旨在为读者提供线段树和并查集的全面理解,特别是它们如何结合使用来解决复杂的连通性问题。我们将探讨这两种数据结构的基本原理、实现方法、性能特点以及实际应用。核心概念与联系:介绍线段树和并查集的基本概念算法原理与实现:详细讲解两种数据结构的实现细节实际应用场景:展示它们在现实问题中的应用性能分析与优化:讨论性能特点和优化技巧总结与展望:回顾要点并探讨未来发展方向线段树(Segment Tree):一种二叉树数据结构,用于高效处理区间查询和更新操作。

AI 算法实战派 948

并查集带权拓展:带权重路径压缩、差分约束、复杂连通性问题实战

本文介绍了带权并查集的扩展应用,重点讲解了带权重路径压缩和差分约束系统的解决方法。文章首先分析了朴素并查集的局限性,指出其无法处理变量间的相对关系问题。随后详细阐述了带权并查集的核心思想,通过引入权重数组实现相对关系的维护。文中提供了带权并查集的Python实现模板,支持路径压缩和权重更新,适用于除法比值、差分约束等多种场景。最后简要提及了差分约束系统的求解方法,展示了带权并查集在复杂连通性问题中的应用价值。文章强调权重定义必须全局统一,并提供了详细的操作逻辑和代码实现。

网络工程师|十多年企业级运维实战|精通 ‌BGP、OSPF、VLAN、SDN、MPLS、ACL、NetFlow、SNMP、 77

并查集:10行代码搞定连通性问题

本文系统介绍了并查集(DSU)数据结构,包括其核心概念、优化方法及实际应用。主要内容包括: 基本结构:使用parent数组表示元素归属,通过find和union操作实现集合管理 优化策略: 路径压缩:查找时将节点直接连接到根,降低后续查询复杂度 按秩合并:根据树高合并集合,保持结构平衡 高效实现:双优化后均摊时间复杂度达O(α(n)),接近常数级 典型应用:Kruskal算法、社交网络分析、环检测等场景 代码模板:提供带双优化的完整实现方案 该数据结构以简洁代码(核心不足10行)高效解决元素分组和连通性问题

2502_93300404的博客 340

并查集算法:解决连通性问题的高效策略

本文深入探讨了并查集算法,这是一种用于快速确定网络中节点连通性的数据结构和算法。通过分析Union-Find API的实现,展示了算法在处理大规模数据时的效率和实际应用。文章以理论为基础,结合实际案例,讨论了并查集在管理连通分量中的关键作用,并对三种不同的实现方式:Quick-Find、Quick-Union以及加权Quick-Union进行了详细分析,揭示了它们在执行效率上的差异。

weixin_36212459的博客 454

免费原神日常一次跑完:genshin_impact_assistant 运行走读与避坑指南

genshin_impact_assistant(GIA)是一个免费开源的原神助手,靠截屏识别加模拟按键自动跑日常:委托、秘境、采集、地脉。适合想把每日任务交给程序、自己只负责养角色的玩家。 ## 🚀 先跑起来:如何本地运行原神助手 环境没得商量:Windows、管理员权限、游戏分辨率 1920x1080。启动时 `source/util.py` 会做 `is_admin()` 检查,不满足

gitblog_00027的博客 1166

Transformer代码(Pytorch实现和详解)!!!

这个是第一版,有些代码如果不对,欢迎在评论指正,后续会慢慢改,我也是刚接触transformer,若有些地方理解不对还请指正。

xml的博客 5612

【移动APP测试】Firebase Test Lab (FTL) 实战指南:从零搭建自动化测试流水线

本文详细介绍了Firebase Test Lab (FTL) 在移动APP测试中的实战应用,从零搭建自动化测试流水线。通过真实设备、虚拟设备和iOS设备的全面覆盖,FTL帮助开发者高效进行兼容性测试、性能监控和崩溃分析,显著提升应用质量。文章还提供了设备选择策略、成本控制技巧和CI/CD集成的最佳实践,助力团队优化测试流程。

weixin_29281915的博客 253

Kiner算法刷题记(六):并查集与连通性问题(手撕算法篇)

547. 省份数量 解题思路 这道题很明显就是连通性问题,一遇到连通性问题,我们第一时间就要想到使用并查集解决,我们使用并查集将所有属于同一个省份的城市放到一个集合中后,我们只需要看一下集合数量便知道能分成几个省份了。 在这里,我们的集合数量其实就是我们并查集中根节点的数量。 代码实现 /* * @lc app=leetcode.cn id=547 lang=typescript * * [547] 省份数量 */ // @lc code=start class UnionSet { /

u010651383的专栏 326

PostgreSQL高可用之主备复制

多个PostgreSQL可协同工作,如果主库发生宕机备库将迅速进行接管并对外提供服务以实现高可用。本文将从主备复制、主备切换、故障转移等角度进行实际测试演练。第一章主备复制是基础,通过主备复制可以得到一个或多个相同的实例。在主备复制的基础上通过第二章主备切换介绍了如何手工将主库与备库互换角色。在第三章中,采用了Keepalived进行实时监测,在主库宕机后,使用主备切换中提到的命令使备库升级为主库并对外提供服务,以达到PostgreSQL高可用的目标。

asdasdsaff的博客 1347

并查集算法:解决连通性问题的终极指南

并查集(Union-Find)是一种高效处理**动态连通性**问题的数据结构,能够快速判断两个元素是否属于同一集合,并支持集合的合并操作。无论是社交网络中的好友关系判断,还是地图中的路径联通性分析,甚至是图像识别中的区域划分,都能看到并查集的身影。本文将带你从基础到进阶,掌握并查集的核心原理与实战应用。 ## 一、并查集的核心概念:解决连通性的利器 ### 1.1 什么是动态连通性? 想象一

gitblog_00554的博客 379

ST MotorControl Workbench 6.2.1 自定义硬件配置避坑指南

本文详细介绍了ST MotorControl Workbench 6.2.1在自定义硬件配置中的常见问题与解决方案,涵盖功率板配置、采样电路校准、电机参数设置及代码生成避坑指南,帮助开发者高效完成电机控制项目开发。

red88的博客 1023

ISO18000-6B/6C(EPC C1G2)两个射频识别(RFID)标准协议的技术特点

目前读写器基本上是采用IMPINJ的R2000芯片和E710芯片开发,因为ISO18000-6B标准的现在应用很少,E710芯片已经不再支持ISO18000-6B标准,选择上就只有采用R2000芯片开发的UR6258超高频读写器以及手持机,这个在项目应用上需要留意。尽管ISO18000-6B标准具有上述优点,但也存在一些不足之处,特别是多标签阅读性能远远满足不了现在的应用需求,近年来发展停滞,绝大部分应用已经被ISO18000-6C(EPC C1G2)取代;#RFID# #物联网# #标准协议#

RFID设备与应用介绍 2156

并查集实战:从原理到优化,解决动态连通性问题

并查集(Union-Find)是一种用于高效处理动态连通性问题的数据结构,其核心思想是通过维护一个父节点数组来管理元素的分组关系。它支持两种基本操作:查找(Find)用于确定元素所属集合的根节点,合并(Union)用于将两个集合合并为一个。通过路径压缩和按秩合并两大优化技术,并查集的操作时间复杂度可降至接近常数级别,从而在处理大规模数据时表现出色。在工程实践中,并查集广泛应用于网络连接、社交网络分析、最小生成树算法(如Kruskal)以及环检测等场景。本文以“七星灯”问题为例,详细解析了并查集的实现原理、优

weixin_30846347的博客 300

XSS漏洞之PDF生成:从XSS到服务端任意文件读取

XSS是最为常见的Web漏洞之一,多年来连续入选OWASP TOP10,相信大家都耳熟能详。 它是一种代码注入类的攻击,是一种客户端侧的攻击,攻击者通过在Web应用中注入恶意JavaScript代码,通过点击URL,最终在受害者浏览器端执行的一种漏洞。主要有反射型XSS、存储型XSS、基于DOM的XSS三类。XSS一些比较常规的危害大概有:重定向浏览器、窃取Cookie、浏览器劫持等。本文章侧重于发现XSS后的进一步利用。 主要介绍在某次实际测试过程中,发现XSS漏洞之后,如何进一步的利用,最终通过XSS达

计算机毕业论文源码,学生个人网页制作html源码。贴近用户做网络推广和互联网优化。 3777

并查集:从原理到实战,掌握动态连通性问题的瑞士军刀

在计算机科学中,处理元素分组与动态连通性问题是算法设计的核心挑战之一。其基本原理在于高效管理集合的合并与查询操作,通过树形结构和父指针映射来抽象表示元素间的归属关系。这一原理的技术价值在于,它为解决大规模网络中的连通性判断提供了近乎常数时间复杂度的解决方案,极大地提升了处理效率。在工程实践中,通过路径压缩和按秩合并两大优化技巧,可以确保并查集在面对海量数据操作时依然保持高性能。其应用场景广泛,从基础的图论算法如Kruskal最小生成树,到社交网络分析、图像处理中的区域标记,乃至电路板布线检查,都能看到它的身

weixin_31421613的博客 213

Multisim14使用教程详尽版--(2025最新版)

摘要:本文详细介绍了Multisim14电路仿真软件的功能和使用方法。主要内容包括:1)主流电路仿真软件比较,突出Multisim在教学、竞赛设计中的优势;2)软件界面说明,涵盖菜单栏、工具栏、元器件库和仪器仪表;3)18类元器件分类详解及其使用操作;4)15种仪器仪表的原理和应用场景;5)电路原理图设计与仿真流程;6)基本电路分析方法(直流静态工作点分析、交流分析等)。文章还提供了硬件工程师笔试面试相关资源链接,涵盖电阻、电容、三极管等器件知识及AD软件操作指南。通过系统讲解,帮助用户掌握Multisim

XU157303764的博客 2万+

C#与天文观测:Celestia模拟星空的奇幻之旅

Celestia就像一艘穿梭在星海中的小飞船,带领我们遨游宇宙。C#则是这艘飞船的智能导航系统,用代码指挥它飞向任何我们向往的星球或星系。首先,下载并安装Celestia,熟悉其基本操作和功能。创建一个星空目标列表,包括不同的恒星、行星和星系。// 示例:定义观察目标列表new SpaceObject("太阳"),new SpaceObject("月球"),new SpaceObject("火星")

java专栏 1456

并查集进阶:从连通性到关系编码,详解食物链问题与带权并查集

并查集(Union-Find)是一种用于高效处理动态连通性问题的数据结构,其核心原理是通过路径压缩与按秩合并来维护元素间的集合归属关系。这一基础数据结构在解决诸如网络连接、图论连通分量等问题上展现出巨大技术价值。然而,当问题场景从简单的“是否连通”扩展到需要维护元素间复杂关系(如捕食、同类、敌对)时,基础并查集便显得力不从心。此时,带权并查集(或称关系型并查集)通过引入“关系偏移量”的概念,将元素间的相对关系编码为到根节点的权值(通常进行模运算),从而能够在保持近似常数时间复杂度的同时,支持对多维关系的查询

weixin_42537919的博客 298

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

《 C++ 修炼全景指南:二十二 》突破算法极限:并查集如何轻松搞定最棘手的连通性问题?

本篇博客深入探讨了并查集(Union-Find Set)的基础概念、实现与优化,涵盖了路径压缩与按秩合并的优化技术,讲解了并查集如何通过这些方法提升效率,达到接近常数时间复杂度 O(α(n)) 。此外,博客详细阐述了并查集在图算法(如 Kruskal 最小生成树)、网络连通性以及数据库系统中的实际应用,并提供了相关的代码实现和性能分析。通过深入剖析并查集的变体、扩展及其在面试中的典型问题,帮助读者在掌握其核心原理的同时,了解在大规模数据和动态更新图中的应用。

Lenyiin 1万+

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

C++并查集:高效解决连通性问题

本文介绍了并查集(Disjoint Set Union)这一高效处理集合合并与查询的数据结构。主要内容包括:1)并查集的核心思想是通过父节点数组管理集合关系;2)基础操作包含初始化、查找根节点和合并集合;3)关键优化路径压缩技术,通过递归查找直接将节点挂到根节点;4)提供了可直接套用的完整模板代码;5)列举了并查集的典型应用场景如图连通性判断、朋友圈关系处理等。文章强调路径压缩是必选优化,能显著提升效率,并建议读者通过练习掌握这一在算法竞赛和面试中频繁出现的数据结构。

澈的博客 357

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

算法入门:并查集(Disjoint Set / Union-Find):连通性问题的利器

摘要 本文以三国时期刘备军队管理为背景,生动解释了并查集(Disjoint Set)数据结构的原理与应用。通过"找头儿"(Find)和"队伍合并"(Union)两个典型场景,展示了并查集判断集合归属和合并集合的核心操作。文章详细介绍了链表实现方式,包括数据结构设计、加权合并启发式算法等关键技术点,并提供了完整的C++代码实现。这种历史故事与技术原理相结合的方式,使得抽象的算法概念变得直观易懂,适合初学者理解并查集的基本思想和实现方法。

2401_87241878的博客 455

DSA 面试精讲 · 第 19 篇 · 并查集:几行代码解决连通性问题

并查集(Union Find / Disjoint Set Union,DSU)是图论中处理连通性问题的核心数据结构,代码不到 20 行,时间复杂度却能达到 O(α(N))(可视为常数)。本文从 LeetCode 547(省份数量)和 684(冗余连接)入手,深入讲解并查集的 parent 数组设计、路径压缩、按秩合并两大优化,并提供 Python/Java/C++ 三语言完整实现。掌握并查集,轻松应对面试中的连通性、环检测类题目。

2401_88352165的博客 358
上一篇: 平衡二叉搜索树:AVL 与红黑树
下一篇: 布隆过滤器与位图
Ricky_Theseus
博客等级 码龄3年 126粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ricky_Theseus

感谢大家,祝您生活愉快

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值