IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【并查集】union和find的几种实现 -> 正文阅读

[数据结构与算法]【并查集】union和find的几种实现


书接上回 union-find算法(并查集),先抛开上文中的 unionfind实现方式不谈。
并查集中, unionfind有以下几种实现方式:
(1) quick-findfind()的时间复杂度是 O(1)union()的是 O(n)
(2) quick-unionfind()的时间复杂度是 O(n)union()的是 O(1)
(3) 加权 quick-union:优化 quick-unionfind()
(4) 路径压缩的加权 quick-union:优化加权 quick-unionfind()

以上指的是单次操作的时间复杂度是,且union里调用find所用的时间不算。

quick-find

保证当且仅当id[p]等于id[q]pq是连通的,即同一连通分量中所有触点在数组中的值全部相同
比如有以下两个连通分量,标识符分别为96
触点3849属于分量9
触点501726属于分量6
在这里插入图片描述

实现

union_find.h

#ifndef UNION_FIND
#define UNION_FIND

#include <vector>

class UF {
public:
    UF(size_t N);
    ~UF();

    size_t Count() const;
    void Union1(size_t p, size_t q);
    size_t Find1(size_t p) const;

private:
    std::vector<size_t> id;
    size_t count_;
};

#endif

union_find.cpp

#include "union_find.h"

UF::UF(size_t N) : id(N)
{
    for (size_t i = 0; i < N; ++i) {
        id[i] = i;
    }
    count_ = N;
}

UF::~UF() {}

void UF::Union1(size_t p, size_t q)  // 连接p所在分量和q所在分量
{
    int fp = Find1(p);
    int fq = Find1(q);

    if (fp == fq) {
        return;
    }

    for (int i = 0; i < id.size(); ++i) {
        if (id[i] == fq) {
            id[i] = fp;  // 把q所在的分量上的所有触点连接到p所在的分量上
        }
    }

    --count_;
}

size_t UF::Find1(size_t p) const   // 返回p的分量标识符
{
    return id[p];
}

size_t UF::Count() const
{
    return count_;
}

分析

这种实现的find()操作的速度是很快的,只需访问一次数组,即O(1)的时间复杂度。但每次的union()操作都需要遍历一次数组,即O(n)的时间复杂度。因此无法处理存在大量触点的问题。

quick-union

每个触点所对应的id数组元素值都是同一个分量中的另一个触点的名称,我们将这种关系称为连接。从某个触点开始,可以找到它连接的另一个触点,再找到下一个连接的触点,直到根触点(连接指向自己)。
当且仅当分别由两个触点开始到达同一个根触点时,它们存在于同一个连通分量之中。
连通分量被表示为“”型结构,可如下表示:96分别是它们所在分量的根触点。
在这里插入图片描述

可以发现,quick-findquick-union的扁平化版本,前者树的深度<=1,后者树的深度<=N

实现

void UF::Union2(size_t p, size_t q)
{
    int fp = Find2(p);
    int fq = Find2(q);
    if (fp == fq) {
        return;
    }

    id[fq] = fp; // 把q所在分量的根触点加在p所在分量的根触点上
    --count_;
}

size_t UF::Find2(size_t p) const
{
    while (p != id[p]) {
        p = id[p];
    }
    return p;
}

分析

find():沿着起始触点一步步地找它对应的连接触点,直至找到根触点并返回它。最差情况下(树会变得很深,每新增一个触点,树的深度都加1),find的时间复杂度为O(n)
union():把一个分量的根触点连接到另一个分量的根触点上,完成两个分量的合并。时间复杂度为O(1)。综合性能比quick-find好一些了。
union(9, 6);
在这里插入图片描述

加权quick-union

find():和quick-union一样;
union():合并两个分量时,多一个判断,把小树加在大树上,防止树变得过深

实现

sz[i]表示以触点i为根的“”所包含的触点个数,即树的大小。

void UF::Union3(size_t p, size_t q)
{
    int fp = Find2(p);
    int fq = Find2(q);
    if (fp == fq) {
        return;
    }

    if (sz[fp] < sz[fq]) {
        id[fp] = fq;
        sz[fq] += sz[fp];
    } else {
        id[fq] = fp;
        sz[fp] += sz[fq];
    }
    --count_;
}

分析

虽然多了一次判断,但union的时间复杂度依然是O(1)
通过防止树变得过深,优化了find,避免了最差情况的发生。

路径压缩的加权quick-union

路径压缩是指尽量让树的结构看起来像quick-find那样扁平,在不损失union()性能的前提下进一步优化find()的时间复杂度。

实现

union操作和加权quick-union的一样。
find操作要遍历两次从当前触点到根触点的路径。第一次找到根触点,第二次使沿途的触点直接指向根触点。

size_t UF::Find4(size_t p) const
{
    int fp = id[p];
    while (fp != id[fp]) { // 找到根触点
        fp = id[fp];
    }

    while (p != fp) {
        int nxt = id[p];
        id[p] = fp; // 将触点直接连接到根触点
        p = nxt;
    }

    return fp;
}

分析

通过在遍历触点的同时将它们直接连接到根触点,进一步降低了树的深度,在保证union性能不变的情况下,优化了find

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-19 01:25:36  更:2022-02-19 01:27:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 15:51:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码