------------------siwuxie095

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

基于 rank 的优化

 
 

 
 

基于
size 的优化,在大多数情况下,都能让生成的树的层数更少,

从而使得查询的时间更短,但仍有少数情况不是这样,如下:

 
 

 
 

 
 

 
 

现在要将 4 和 2 这两个元素并在一起,4 对应的根是 8,2 对应的根是 7,

其中: 8 所在的集合一共有 3 个元素,而 7 所在的集合一共有 6 个元素,

显然,基于
size 的优化,经过 Union 操作后,就应该是下面的样子:

 
 

 
 

 
 

 
 

注意:原来两棵树的层数分别为 2 和 3,合并后层数却变成了 4,

但假如换一个方向,将 7 的指向父亲的指针指向 8 的话,得到的

新树的层数为 3,比刚才的做法层数要少,如下:

 
 

 
 

 
 

 
 

 
 

 
 


依靠集合的
size 来判断由谁指向谁,并不是完全准确的,更准确

的方式是:根据两个集合所表示的树的层数来判断由谁指向谁

 
 

在并查集中,通常使用一个叫做
rank 的数组来表示层数。设立一个

rank 数组,rank[i] 表示根节点为 i 的树的高度

 
 

 
 

 
 

 
 

 
 

程序:基于
rank 的优化

 
 

UnionFind.h:

 
 

#ifndef UNIONFIND_H

#define UNIONFIND_H

 
 

#include <cassert>

using namespace std;

 
 

 
 

 
 

//并查集:Quick Union + rank

namespace UF

{

 
 

class UnionFind

{

 
 

private:

int* parent;

int* rank; // rank[i]表示以i为根的集合所表示的树的层数

int count;

 
 

public:

UnionFind(int count)

{

this->count = count;

parent = new
int[count];

rank = new
int[count];

//在初始情况下,并查集里的元素,两两之间互不连接

for (int i = 0; i < count; i++)

{

parent[i] = i;

rank[i] = 1;

}

}

 
 

 
 

~UnionFind()

{

delete []parent;

delete []rank;

}

 
 

 
 

int find(int p)

{

assert(p >= 0 && p < count);

//不断追溯,直到p等于parent[p],即 p 为根节点,返回 p

//(返回的是根节点)

while (p != parent[p])

{

p = parent[p];

}

 
 

return p;

}

 
 

 
 

bool isConnected(int p, int q)

{

return find(p) == find(q);

}

 
 

 
 

void unionElements(int p, int q)

{

 
 

int pRoot = find(p);

int qRoot = find(q);

 
 

if (pRoot == qRoot)

{

return;

}

 
 

//rank小的那棵树的根节点指向rank大的那棵树的根节点

if (rank[pRoot] < rank[qRoot])

{

parent[pRoot] = qRoot;

}

else if (rank[qRoot] < rank[pRoot])

{

parent[qRoot] = pRoot;

}

// rank[pRoot] == rank[qRoot]

else

{ //可互换

parent[pRoot] = qRoot;

rank[qRoot] += 1;

}

}

};

}

 
 

 
 

#endif

 
 

 
 

 
 

UnionFindTestHelper.h:

 
 

#ifndef UNIONFINDTESTHELPER_H

#define UNIONFINDTESTHELPER_H

 
 

#include
"UnionFind.h"

#include <iostream>

#include <ctime>

using namespace std;

 
 

 
 

 
 

namespace UnionFindTestHelper

{

 
 

void testUF(int n)

{

//设置随机种子

srand(time(NULL));

UF::UnionFind uf = UF::UnionFind(n);

 
 

time_t startTime = clock();

 
 

//先进行n次的并,即 Union 操作

for (int i = 0; i < n; i++)

{

int a = rand() % n;

int b = rand() % n;

uf.unionElements(a, b);

}

 
 

//再进行n次的查,即 Find 操作

for (int i = 0; i < n; i++)

{

int a = rand() % n;

int b = rand() % n;

uf.isConnected(a, b);

}

 
 

time_t endTime = clock();

 
 

//打印2*n个操作耗费的时间

cout << "UF, " << 2 * n << " ops, " << double(endTime - startTime) / CLOCKS_PER_SEC

<< " s" << endl;

}

}

 
 

 
 

#endif

 
 

 
 

 
 

main.cpp:

 
 

#include
"UnionFindTestHelper.h"

#include <iostream>

using namespace std;

 
 

 
 

 
 

int main()

{

//规模是一百万

int n = 1000000;

 
 

UnionFindTestHelper::testUF(n);

 
 

system("pause");

return
0;

}

 
 

 
 

运行一览:

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

【made by siwuxie095】

基于rank的优化的更多相关文章

  1. CBO 基于成本的优化器[基础]

    转载:CBO基于成本的优化器 ----------------------------------2013/10/02 CBO基于成本的优化器:让oracle获取所有执行计划的相关信息,通过对这些信息 ...

  2. Apache Spark 2.2中基于成本的优化器(CBO)(转载)

    Apache Spark 2.2最近引入了高级的基于成本的优化器框架用于收集并均衡不同的列数据的统计工作 (例如., 基(cardinality).唯一值的数量.空值.最大最小值.平均/最大长度,等等 ...

  3. 基于size的优化

    ----------------------siwuxie095                                 基于 size 的优化         在 union( p , q ...

  4. 基于粒子群优化的无约束50维Rosenbrock函数求解

    基于粒子群优化的无约束50维Rosenbrock函数求解 一.问题重述 无约束50维的Rosenbrock函数可以描述如下: 其中, 0 要求按PSO算法思想设计一个该问题的求解算法. Rosenbr ...

  5. 基于Raft深度优化,腾讯云金融级消息队列CMQ高可靠算法详解

    背景介绍 分布式系统是指一组独立的计算机,通过网络协同工作的系统,客户端看来就如同单台机器在工作.随着互联网时代数据规模的爆发式增长,传统的单机系统在性能和可用性上已经无法胜任,分布式系统具有扩展性强 ...

  6. Spark SQL 性能优化再进一步:CBO 基于代价的优化

    摘要: 本文将介绍 CBO,它充分考虑了数据本身的特点(如大小.分布)以及操作算子的特点(中间结果集的分布及大小)及代价,从而更好的选择执行代价最小的物理执行计划,即 SparkPlan. Spark ...

  7. MySQL 并行复制演进及 MySQL 8.0 中基于 WriteSet 的优化

    MySQL 8.0 可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前 Generally Available 版本已经已经发布,正式版本即将发布,在此将介绍8.0版本中引入的一 ...

  8. <强化学习>基于采样迭代优化agent

    前面介绍了三种采样求均值的算法 ——MC ——TD ——TD(lamda) 下面我们基于这几种方法来 迭代优化agent 传统的强化学习算法 || ν ν 已经知道完整MDP——使用价值函数V(s) ...

  9. 概述:基于事件的优化方法 / 事件驱动优化 / Event-Based Optimization / EBO

    大家好,我是月出 本文基于这篇综述,介绍了 事件驱动优化(Event-Based Optimization, EBO). 事件驱动优化,是一种建模现实场景.做优化的思路,理论和 MDP / 强化学习很 ...

随机推荐

  1. Python创建CRNN训练用的LMDB数据库文件

    CRNN简介 CRNN由 Baoguang Shi, Xiang Bai, Cong Yao提出,2015年7月发表论文:"An End-to-End Trainable Neural Ne ...

  2. libwebsockets 运行问题

    /****************************************************************************** * libwebsockets 运行问题 ...

  3. (二)canvas边框问题

    lineWidth 设置边框的大小 fillStyle 设置div的颜色 strokeStyle 设置边框的颜色 注: 边框在不设置的情况下默认为1px 黑色,但是x,y轴的距离是以图形的正中心为原始 ...

  4. 21天学通C++_Day3_Part2

    0.语句的分行 法1:在第一行末尾添加反斜杠 cout<<"Hello \ World!"<<endl; 法2:将字符串字面量分成两个,编译器注意到两个响铃 ...

  5. Git学习资源收集汇总

    伴随着知乎上一个问题:GitHub 是怎么火起来的?被顶起200+的回答说到:Github不是突然火起来的,在Ruby社区Github其实从一开始就很流行,我们2009年搞Ruby大会就邀请了Gith ...

  6. python 不同版本下载资源

    Unofficial Windows Binaries for Python Extension Packages by Christoph Gohlke, Laboratory for Fluore ...

  7. 使用微软的MSBuild.exe编译VS .sln .csproj 文件

    最近在看一些算法和测试一些程序,以及帮团队测试程序,团队使用了vs开发环境创建的sln项目文件,我使用的是公司的机器,没有任何权限安装程序等操作,但是又需要编译一些程序,所以我想到了,使用MSBuil ...

  8. GZip压缩与解压缩

    GZIP的压缩与解压缩代码: public static class CompressionHelper { /// <summary> /// Compress the byte[] / ...

  9. Spring BeanPostProcessor与动态加载数据源配置

    前言: 本文旨在介绍Spring动态配置数据源的方式,即对一个DataSource的配置诸如jdbcUrl,user,password,driverClass都通过运行时指定,而非由xml静态配置定死 ...

  10. 利用ffmpeg一步一步编程实现摄像头采集编码推流直播系统

    了解过ffmpeg的人都知道,利用ffmpeg命令即可实现将电脑中摄像头的画面发布出去,例如发布为UDP,RTP,RTMP等,甚至可以发布为HLS,将m3u8文件和视频ts片段保存至Web服务器,普通 ...