当前位置: 首页 > news >正文

并查集的优化

在上期的文章中我们把并查集的具体操作写了出来,写完之后的代码时间复杂度

Find()函数为O(log2n)
Union()函数为O(nlog2n)

这在我们常规的数据结构算法中的时间复杂度已经很小了,但是如果我们在并查集中多次的查找和合并的话,时间复杂度还是很大,今天我给大家介绍一种在足够多的使用查找和合并的情况下的一种时间复杂度非常小的算法:

代码如下:

#include<stdio.h>
#include<stdbool.h>
#include<limits.h>
#define SIZE 13 //假设长度为13
typedef struct Node
{
char data;//数据域
int parent;//父结点
}Node;
typedef struct Gather
{
Node arr[SIZE];//数组长度
}Gather;
//初始化集合
void Initial(Gather* S)
{
int i = 0;
for (i = 0; i < SIZE; i++)
{
S->arr[i].parent = -1;//都设置为-1,每一个结点都是一个独立的集合
}
}
//插入结点
bool EnNode(Gather* S)
{
int i = 0;
for (i; i < SIZE; i++)
S->arr[i].data = 'A' + i;//依次插入A-M
return true;
}

//查找结点的所属的集合
int Find(Gather* S, int x)
{
if (S == NULL)
return INT_MIN;
//优化前的方案
//while (S->arr[x].parent >= 0)//如果父节点不是根结点
//    x = S->arr[x].parent;//一直向上找


//优化后方案
//查找根结点
int root = x;
while (S->arr[root].parent >= 0)
root = S->arr[root].parent;

//把路径上的结点直接连接到根结点
while (x != root)
{
int t = S->arr[x].parent;
S->arr[x].parent = root;
x = t;
}
return root;
}
//合并两棵树所属的集合
bool Union(Gather* S, int x, int y)
{
if (S == NULL)
return false;
int Root1 = Find(S, x);
int Root2 = Find(S, y);
if (Root1 == Root2)
return false;//如果是同一个集合则直接返回
if (S->arr[Root2].parent > S->arr[Root1].parent)//代表Root1中元素大于Root2中的元素
{
S->arr[Root1].parent += S->arr[Root2].parent;//把Root2中的结点数量加到Root1中
S->arr[Root2].parent = Root1;//将Root2连接到Root1上
}
if (S->arr[Root2].parent <= S->arr[Root1].parent)//代表Root2中元素大于Root1中的元素
{
S->arr[Root2].parent += S->arr[Root1].parent;//把Root2中的结点数量加到Root1中
S->arr[Root1].parent = Root2;//将Root2连接到Root1上
}
return true;
}

int main()
{
Gather S;
Initial(&S);//初始化结点
EnNode(&S);//插入结点
//建立链接
Union(&S, 0, 1);
Union(&S, 1, 4);
Union(&S, 1, 5);
Union(&S, 4, 10);
Union(&S, 4, 11);

    Union(&S, 2, 6);

    Union(&S, 3, 7);
Union(&S, 3, 8);
Union(&S, 3, 9);
Union(&S, 7, 12);

    //合并其他树
Union(&S, 6, 4);//合并两个树
Union(&S, 0, 3);//全部合并


return 0;
}

相比于上期的代码,主要修改了Find函数的中操作,具体思想是:

先找到根结点,再将查找路径上所有节点都挂到根结点下

这样做在调用Find函数足够多的情况下时间复杂度不会超过O(5)

具体Find的时间复杂度为O(α(n))

具体Union的时间复杂度为O(nα(n))

α(n)是一种增长速度及其缓慢的函数,为阿克曼函数的反函数,这涉及到计算机科学和数学的内容,总之假设n = 10⁸⁰(宇宙的原子数量),Find(α(n))的复杂度也不会大于O(5)

http://www.dtcms.com/a/449835.html

相关文章:

  • LeetCode:93.最长回文子串
  • 设计作品网站有哪些宝塔建的数据库安装不了wordpress
  • 锐捷无线控制器基础配置
  • mineru处理后的文档生成对应层级的标题
  • 台山网站建设公司公司网站建设如何撤销
  • 辛集做网站公司麻豆秋白色蕾丝半身裙
  • Java:面向对象:内部类:静态内部类与非静态内部类的比较
  • 基于32位MCU的LVGL移植
  • 基于STM32单片机的语音控制智能停车场设计
  • (Kotlin协程十三)Dispatchers.Main, IO, Default 分别适用于什么场景?它们的底层是什么?
  • 郑州网站建设 seo郑州网络营销公司哪家好
  • 中山精品网站建设信息手机可以创建网站吗
  • 学习Java第三十二天——黑马点评43~47
  • 宿迁网站推广公司做企业宣传网站
  • 优选算法-双指针:6.和为s的两个数字
  • [linux仓库]System V 进程通信详解:System V消息队列、信号量
  • css过渡属性
  • Linux系统--文件系统--动静态库
  • Spring进阶 - SpringMVC实现原理(二)DispatcherServlet处理请求的过程
  • SQL 面试高频:INNER JOIN vs LEFT JOIN 怎么考?
  • 【51单片机】【protues仿真】基于51单片机智能路灯控制系统
  • 3d模型免费素材网站wordpress如何修改行距
  • 再探类对象——C++入门进阶
  • 公司网站如何维护wordpress去掉title前空格及keywords最后的逗号
  • 仙居谁认识做网站的广告投放平台代理
  • 智慧餐厅管理系统qq群排名优化软件官网
  • InnoDB核心限制与应对策略
  • 贵州建设厅监理协会网站前后端分离实现网站开发
  • QNX 开发环境搭建
  • Java技术栈 —— 使用MinIO进行大文件分片上传与下载