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

 
 

 
 

 
 

 
 

 
 

 
 

 
 

 
 

基于 size 的优化

 
 

 
 


union( p , q ) 的时候,因为总是将第一个元素的根节点指向第二个元素

的根节点,就有可能让整棵树变的很高,导致
find( p ) 更耗时

 
 

 
 

解决方案:不应该固定的将一个元素的根节点指向另外一个元素的根节点,

而应该在做具体的指向操作之前,进行一下判断:判断两个元素所在集合

的元素总数谁大谁小

 
 

 
 

具体实现:存储每一个集合中元素的个数,在进行
Union 操作时,永远将

元素少的那组集合的根节点指向元素多的那组集合的根节点

 
 

这样一来,将会有更高概率形成一棵层数比较低的树

 
 

 
 

 
 

 
 

 
 

程序:基于
size 的优化

 
 

UnionFind.h:

 
 

#ifndef UNIONFIND_H

#define UNIONFIND_H

 
 

#include <cassert>

using namespace std;

 
 

 
 

 
 

//并查集:Quick Union + size

namespace UF

{

 
 

class UnionFind

{

 
 

private:

int* parent;

int* sz; // sz[i]表示以i为根的集合中元素个数

int count;

 
 

public:

UnionFind(int count)

{

this->count = count;

parent = new
int[count];

sz = new
int[count];

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

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

{

parent[i] = i;

sz[i] = 1;

}

}

 
 

 
 

~UnionFind()

{

delete []parent;

delete []sz;

}

 
 

 
 

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;

}

 
 

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

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

{

parent[pRoot] = qRoot;

sz[qRoot] += sz[pRoot];

}

else

{

parent[qRoot] = pRoot;

sz[pRoot] += sz[qRoot];

}

}

};

}

 
 

 
 

#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】

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

  1. 基于rank的优化

    ------------------siwuxie095                                 基于 rank 的优化         基于 size 的优化,在大多数情况下 ...

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

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

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

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

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

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

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

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

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

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

  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. rem第一天

    Rem为单位 CSS3的出现,他同时引进了一些新的单位,包括我们今天所说的rem.在W3C官网上是这样描述rem的——“font size of the root element” .下面我们就一起来 ...

  2. (效果二)js实现两个变量值的交换

    ES5: var a = 12,b=13,c; c = a; a = b; b = c; console.log(a,b);//13,12 通过设置第三方变量交换赋值来实现   ES6 var a = ...

  3. IntelliJ IDEA下SVN配置及使用

    一.在IDEA中使用SVN,首先需要下载安装 TortoiseSVN 插件. 打开 TortoiseSVN 下载地址,选择适合自己的系统类型下载. 接下来,进行安装即可.选择Modify,默认 com ...

  4. [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBuild+GitHub)

    本系列文章包含: [独孤九剑]持续集成实践(一)- 引子 [独孤九剑]持续集成实践(二)– MSBuild语法入门 [独孤九剑]持续集成实践(三)- Jenkins安装与配置(Jenkins+MSBu ...

  5. 十、python沉淀之路--高阶函数初识

    一.高阶函数:分两种:一种是返回值中包含函数体:另一种是把一个函数体当作了参数传给了另一个函数 1.返回值中包含函数体 例1. def test(): print('这是一个测试') return t ...

  6. haproxy中两个常用的宏

    list_for_each(pos, head) pos.head 都为list类型 一般来说,head是list的虚拟头,依次取list上的各个节点 container_of(ptr, type, ...

  7. Xcode 打开playground文件的时候提示-Unable to find execution service for selected run destination

    解决办法: step 1: 关闭Xcode (快捷键cmd + q) step 2:在terminal里面运行如下语句 rm -rf ~/Library/Developer/CoreSimulator ...

  8. 20位活跃在Github上的国内技术大牛

    登录|注册     leon-这个程序员不闷骚的博客 喜欢leon,有追求有原则有爱心的杀手,做一个有追求的程序员,代码是程序员的朋友,虽然没有热情,但是非常忠实.希望拥有一身绝世武功,再配一把绝世好 ...

  9. Memcached数据存储方式

    1. memcached的数据存储方式被称为Slab Allocator,其基本方式是: ①:先把内存分成很多Slab,这个大小是预先规定好的,已解决内存碎片的问题.分配给Slab的内存空间被称为Pa ...

  10. JDK 8 - Lambda Expression 的优点与限制

    我们知道 JDK 8 新增了 Lambda Expression 这一特性. JDK 8 为什么要新增这个特性呢? 这个特性给 JDK 8 带来了什么好处? 它可以做什么?不可以做什么? 在这篇文章, ...