前言:本文介绍了并查集的优化方案和图的2种基本的遍历方式。
并查集的优化:
普通的并查集可以看看我的这篇文章:高阶数据结构-->图(上)-CSDN博客
先来谈谈为什么要优化?
原先的并查集在面对一些极端情况时,查找根的效率会降低不少,举个例子:
示例:
此时当我们要查找5的根的时候,会不断往上更新,直到找到1为止,类比到海量数据时,速度降低的会愈发明显,所以我们可以通过路径压缩的方式来优化。
如何进行路径压缩?其实很简单,我们只需要在查找某个元素的双亲节点时,同时直接将该元素路径上的所有非root的元素的root修改为root即可!是不是有点绕?没关系,直接上代码解释:
int findRoot(int x)
{
int root = x;
while (_ufs[root] >= 0)
{
root = _ufs[root];
}
/*路径压缩*/
while (_ufs[x] >= 0)
{
int parent = _ufs[x];
_ufs[x] = root;
x = parent;
}
return root;
}
路径压缩时,当查找的元素的值不是root的下标时,直接更新为root,再继续向上更新,直到将该路径上所有的元素的值都更新为root的下标。这样的话结果就会变成:
很明显,此时我们再查找元素5的时候,就只需要查找一次即可,极大的加快了查找root的速度。
另一个小优化:union元素时,用数据量小的一方去合并数据量大的一方,直接上代码:
void Union(int x, int y)
{
int rootX = findRoot(x);
int rootY = findRoot(y);
/*当x和y在同一个集合中的时候,就不用合并直接返回即可*/
if (rootX == rootY)
{
return;
}
//小优化-->数据量小的去合并。
if (abs(_ufs[rootX]) < abs( _ufs[rootY]))
{
swap(rootX, rootY);
}
_ufs[rootX] += _ufs[rootY];
_ufs[rootY] = rootX;
}
原理和路径压缩类似,在这里就不过多赘述。
图的遍历
1.广度优先遍历(BFS)
需要的辅助数据结构:queue(队列),一般还需要一个vis数组来记录顶点.
原理图示:
基础代码模板:
/*以int为例*/
queue<int> q1;
/*先插入起点*/
q1.push(root);
while (q1.size())
{
int sz = q1.size();
for (int i = 0; i < sz; i++)
{
int front = q1.front();
q1.pop();
//判断是否在vis记录过
if (vis[...] == false && /*合法的位置*/)
{
//将front连接的元素入队
q1.push(...);
/*记录该元素*/
vis[...] = true;
}
}
}
/*当队列为空时,遍历结束*/
2.深度优先搜索(DFS)
原理:将一个元素为起点遍历完它的所有可能路径,再去遍历其他元素。
基础代码模板:
一般采用递归的方式写,没有太具体的模板,只能时多练习,画出决策树。
标签:q1,ufs,--,高阶,元素,int,rootY,数据结构,root From: https://blog.csdn.net/2302_80207345/article/details/141650570