基于rank的优化
------------------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 rank = new //在初始情况下,并查集里的元素,两两之间互不连接 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 #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 #include <iostream> using namespace std; int main() { //规模是一百万 int n = 1000000; UnionFindTestHelper::testUF(n); system("pause"); return } |
运行一览:

【made by siwuxie095】
基于rank的优化的更多相关文章
- CBO 基于成本的优化器[基础]
转载:CBO基于成本的优化器 ----------------------------------2013/10/02 CBO基于成本的优化器:让oracle获取所有执行计划的相关信息,通过对这些信息 ...
- Apache Spark 2.2中基于成本的优化器(CBO)(转载)
Apache Spark 2.2最近引入了高级的基于成本的优化器框架用于收集并均衡不同的列数据的统计工作 (例如., 基(cardinality).唯一值的数量.空值.最大最小值.平均/最大长度,等等 ...
- 基于size的优化
----------------------siwuxie095 基于 size 的优化 在 union( p , q ...
- 基于粒子群优化的无约束50维Rosenbrock函数求解
基于粒子群优化的无约束50维Rosenbrock函数求解 一.问题重述 无约束50维的Rosenbrock函数可以描述如下: 其中, 0 要求按PSO算法思想设计一个该问题的求解算法. Rosenbr ...
- 基于Raft深度优化,腾讯云金融级消息队列CMQ高可靠算法详解
背景介绍 分布式系统是指一组独立的计算机,通过网络协同工作的系统,客户端看来就如同单台机器在工作.随着互联网时代数据规模的爆发式增长,传统的单机系统在性能和可用性上已经无法胜任,分布式系统具有扩展性强 ...
- Spark SQL 性能优化再进一步:CBO 基于代价的优化
摘要: 本文将介绍 CBO,它充分考虑了数据本身的特点(如大小.分布)以及操作算子的特点(中间结果集的分布及大小)及代价,从而更好的选择执行代价最小的物理执行计划,即 SparkPlan. Spark ...
- MySQL 并行复制演进及 MySQL 8.0 中基于 WriteSet 的优化
MySQL 8.0 可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前 Generally Available 版本已经已经发布,正式版本即将发布,在此将介绍8.0版本中引入的一 ...
- <强化学习>基于采样迭代优化agent
前面介绍了三种采样求均值的算法 ——MC ——TD ——TD(lamda) 下面我们基于这几种方法来 迭代优化agent 传统的强化学习算法 || ν ν 已经知道完整MDP——使用价值函数V(s) ...
- 概述:基于事件的优化方法 / 事件驱动优化 / Event-Based Optimization / EBO
大家好,我是月出 本文基于这篇综述,介绍了 事件驱动优化(Event-Based Optimization, EBO). 事件驱动优化,是一种建模现实场景.做优化的思路,理论和 MDP / 强化学习很 ...
随机推荐
- I.MX6 PHY fixup 调用流程 hacking
/********************************************************************************** * I.MX6 PHY fixu ...
- Python笔记-2
一.列表的定义及操作 列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作. 1.列表的格式及赋值 列表,使用中括号括起来,元素之间用逗号隔开,列表中的元素具有明确的位 ...
- nodejs docker 开发最好选择yarn 进行包管理而不是npm
npm 与yarn 的区别网上一大堆的文章,我们在构建docker 镜像是应该遵守的有些原则 基础镜像尽量小 对于构建进行缓存处理 构建的docker 的文件层数尽量少 能直接运行的,就别进行重复 ...
- jslinq 使用总结
最近一直在用 jslinq 感觉还是不错的.用于增强 Array.find() 上重点: 1: 引用 cnpm install jslinq --save (本人用淘宝镜像--npmFQ感觉也不快-- ...
- NPOI时间格式判断
switch (cell.CellType) { case CellType.BLANK: //空数据类型处理 dr[iRow] = ""; break; case CellTyp ...
- FastAdmin 社区 FAQ 帖子收集(F4NNIU 版 2018-08-12)
FastAdmin 社区 FAQ 帖子收集 为什么Selectpage下拉列表在编辑时总是返回第一行的值? https://forum.fastadmin.net/thread/2399 根据条件值判 ...
- 使用 Git 来备份 MySQL 数据库
使用 Git 来备份 MySQL 数据库 使用 mysqldump 导出 sql 文件 使用 git pull 提交到仓库 将脚本加入任务管理 mysqldump 导出时需要以下参数. --skip- ...
- thinkphp的select和find的区别(转)
做普通PHP项目转thinkphp时,字段自动完整匹配,ajax时前台数据一直取不到,后发现是select和find返回数据集有差异,参考下面方法修改. $this->ajaxReturn($m ...
- bzoj 3501 PA2008 Cliquers Strike Back——贝尔数
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3501 用贝尔三角形 p^2 地预处理 p 以内的贝尔数.可以模(mod-1)(它是每个分解下 ...
- 容器中跨主机的网络方案-Weave
容器中的网络是建立docker集群的重要内容. 本文将介绍如何用Weave实现容器的多节点互通. Weave是一个开源的项目,其网站为: https://www.weave.works/ 其工作原理相 ...