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

做网站商城项目的流程宜兴网站建设

做网站商城项目的流程,宜兴网站建设,网站建设的域名续费,北京怎么做网站推广标题:[数据结构高阶]并查集初识、手撕、可以解决哪类问题? 水墨不写bug 文章目录 一、认识并查集二、模拟实现并查集三、用并查集解决问题1、[省份的数量](https://leetcode.cn/problems/number-of-provinces/)2、[等式方程的可满足性](https://leetcode…

标题:[数据结构高阶]并查集初识、手撕、可以解决哪类问题?
@水墨不写bug


在这里插入图片描述


文章目录

  • 一、认识并查集
  • 二、模拟实现并查集
  • 三、用并查集解决问题
    • 1、[省份的数量](https://leetcode.cn/problems/number-of-provinces/)
    • 2、[等式方程的可满足性](https://leetcode.cn/problems/satisfiability-of-equality-equations/)
  • 四、并查集的路径压缩


一、认识并查集

一个考察队要去西部开发考察,这个考察队队员有10人,其中郑州4人,北京3人,西安3人。于是这三个城市的人由于生活习惯相似分别抱团,那么如何快速确定两个人是否属于同一个城市呢?并查集就可以。

并查集 :本质是一个森林(包含多棵树)。并且与堆类似,用下标表示关系。使用双亲表示法(只存储双亲)。
如何用数据结构表示并查集?
用一个线性结构(数组)表示。每一个位置都初始化为-1,表示10棵树:
在这里插入图片描述
假如0,6,7,8是郑州人1,4,9是北京人2,3,5是西安人,那么通过树形结构表示(默认下标最小的0,1,2作为小队长- - -根节点):
在这里插入图片描述
如果有新成员加入?
数组对应的队员的值存储的是队长的下标,队长的值的绝对值表示包括队长在内的小队成员个数。队长的值原来为-1,一个队员加入小队,队长的值+=队员的值(-1)|如果队员是队长,则+=(-m),然后队员的值修改为队长的值。

在线性的数组上,需要明确:

  • 1.一个位置值是负数,那它就是数的根,这个负数的绝对值就是这棵树的数据个数。
  • 2.一个位置值是正数,那这个位置存的是双亲的下标。

那么上图对应的线性结构是:
在这里插入图片描述

如果两队伍合并?
由于研究工作需要,北京人和郑州人需要合并,那么在数据结构上如何表示?
其实,把北京人合并入郑州,把郑州人合并入北京,没有本质区别。
假如把北京人合并入郑州,那么对应的树形结构变成:
在这里插入图片描述
那么对应的线性结构:
在这里插入图片描述
这就是并查集的加入一个成员,一个小队的操作。想要看两个队员是否在同一组,只需要不停找根,如果两个队员同根,那就在同一组。


二、模拟实现并查集

并查集可以通过一个STL的vector维护,具体实现思路已经在上文有所体现,于是在这里直接给出实现:

#pragma once
#include<iostream>
#include<vector>
namespace ddsm
{class UnionFindSet{public://根据并查集规则,初始化为-1UnionFindSet(int size):_ufs(size,-1){}//把两个集合【队伍】合并void Union(int x1,int x2){int root1 = FindRoot(x1);int root2 = FindRoot(x2);if (root1 == root2)return;_ufs[root1] += _ufs[root2];_ufs[root2] = root1;}//找到一个元素所在的集合int FindRoot(int x){int parents = x;while (_ufs[parents] >= 0)parents = _ufs[parents];return parents;}//判断两个元素是否在同一个集合bool InSameSet(int x1, int x2){return FindRoot(x1) == FindRoot(x2);}//返回集合的个数size_t Size(){size_t size = 0;for (int i = 0; i < _ufs.size(); ++i){if (_ufs[i] < 0)size++;}return size;}private:std::vector<int> _ufs;};
};

三、用并查集解决问题

通过以上例子可知,并查集一般可以解决一下问题:

  1. 查找元素属于哪个集合 --沿着数组表示树形关系以上一直找到根(即:树中中元素为负数的位置)
  2. 查看两个元素是否属于同一个集合 --沿着数组表示的树形关系往上一直找到树的根,如果根相同表明在同一个集合,否则不在。
  3. 将两个集合归并成一个集合 --将两个集合中的元素合并将一个集合名称改成另一个集合的名称
  4. 集合的个数 --遍历数组,数组中元素为负数的个数即为集合的个数。

1、省份的数量

本题通过把同一省份的城市放在同一集合中,遍历所有城市链接情况,最后统计出省份(集合)的总数。
在这里插入图片描述
在这里插入图片描述
示例代码:

class UnionFindSet
{
public://根据并查集规则,初始化为-1UnionFindSet(int size):_ufs(size,-1){}//把两个集合【队伍】合并void Union(int x1,int x2){int root1 = FindRoot(x1);int root2 = FindRoot(x2);if (root1 == root2)return;_ufs[root1] += _ufs[root2];_ufs[root2] = root1;}//找到一个元素所在的集合int FindRoot(int x){int parents = x;while (_ufs[parents] >= 0)parents = _ufs[parents];return parents;}//判断两个元素是否在同一个集合bool InSameSet(int x1, int x2){return FindRoot(x1) == FindRoot(x2);}//返回集合的个数size_t Size(){size_t size = 0;for (int i = 0; i < _ufs.size(); ++i){if (_ufs[i] < 0)size++;}return size;}
private:std::vector<int> _ufs;
};
class Solution {
public:int findCircleNum(vector<vector<int>>& isConnected) {UnionFindSet ufs(isConnected.size());for(int i = 0;i < isConnected.size();++i){for(int j = 0;j < isConnected[i].size();++j){if(isConnected[i][j] == 1)ufs.Union(i,j);}}return ufs.Size();}
};

但是每次都手撕一个并查集,还是麻烦,那就面向过程的来维护并查集ufs,代码如下:

class Solution {
public:int findCircleNum(vector<vector<int>>& isConnected) {vector<int> ufs(isConnected.size(),-1);auto findroot = [&ufs](int x){while(ufs[x] >= 0) x = ufs[x]; return x;};for(int i = 0;i < isConnected.size();++i){for(int j = 0;j < isConnected[i].size();++j){if(isConnected[i][j] == 1){int rooti = findroot(i);int rootj = findroot(j);if(rooti == rootj)continue;else{ufs[rooti] += ufs[rootj];ufs[rootj] = rooti;}}}}int ret = 0;for(int i = 0;i < ufs.size();++i)if(ufs[i] < 0)++ret;return ret;}
};

2、等式方程的可满足性

分两遍:
第一遍设置集合关系,哪一个元素属于哪一个集合先划分好;
第二遍查找相悖,有相悖,返回false;否则true。

在这里插入图片描述

在这里插入图片描述

class Solution {
public:bool equationsPossible(vector<string>& equations) {vector<int> ufs(26,-1);auto findroot = [&ufs](int x){while(ufs[x] >= 0)x = ufs[x];return x;};//第一遍先设置集合关系for(int i = 0;i < equations.size();++i){if(equations[i][1] == '='){int root1 = findroot(equations[i][0] - 'a');int root2 = findroot(equations[i][3] - 'a');if(root1 != root2){ufs[root1] += ufs[root2];ufs[root2] = root1;}}}//第二次再查找相悖关系for(int i = 0;i < equations.size();++i){if(equations[i][1] == '!'){int root1 = findroot(equations[i][0] - 'a');int root2 = findroot(equations[i][3] - 'a');if(root1 == root2){return false;}}}//没有相悖返回真return true;}
};

四、并查集的路径压缩

随着一棵树的高度增加,并查集的查找效率逐渐降低。路径压缩目的是减小树的高度,进而提高并查集查找效率。
路径压缩一般来说有两种思路:
**第一种:**每次查找一个位置,吧一个节点的位置直接更新到根。
**第二种:**每查找一个位置,把查找路径上的节点位置都更新到根。

到这里并查集结束了,并查集是为了给图做铺垫。


完~
转载请注明出处

在这里插入图片描述

http://www.dtcms.com/wzjs/382145.html

相关文章:

  • 做网站域名怎么选有利于seo百度竞价推广开户费用
  • 建设小说网站费用留手机号广告
  • 有哪些做动图网站武汉seo软件
  • 建站教学seo网站快速排名软件
  • 定西临洮网站建设手机优化大师下载2022
  • 合肥企业网站制作方案百度引擎搜索入口
  • 荣耀商城官网网站网站排名点击工具
  • 网站负责人 法人谷歌sem推广
  • 16岁做分期网站百度推广怎么开户
  • erp系统与网站对接长沙手机端竞价恶意点击能防止吗
  • 画廊网站模板苏州seo关键词优化方法
  • 做网站封面要怎么做鸡西seo顾问
  • 青岛网站运营推广seo排名优化推荐
  • 微信网页注册入口seo关键词优化
  • 怎么做竞拍网站百度关键词推广一年多少钱
  • 集安网站制作电商怎么做营销推广
  • 做画找图网站江苏建站
  • 企业网站展示生产的处方药介绍处罚案件企业建站系统
  • 厦门住房建设局网站首页百度搜索高级搜索技巧
  • 网络空间安全专业郑州网站seo服务
  • 2020一建试题seo教程自学入门教材
  • 网站的推广等内容成都网站关键词推广
  • 大门户wordpress主题门户新闻seo全网优化指南
  • 网站域名需要购买吗长沙电商优化
  • 泰安网站建设入门泉州全网营销优化
  • 网站做响应式还是移动端郑州网络推广方案
  • wordpress自制主题优化电脑的软件有哪些
  • 微信分销网站建设电话东莞网络推广招聘
  • 如何查询网站二级页面流量海外新闻发布
  • 深圳 赢客创想网络技术股份有限公司 网站建设百度seo关键词优化推荐