高阶数据结构-->图(中)

前言:本文介绍了并查集的优化方案和图的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)

原理:将一个元素为起点遍历完它的所有可能路径,再去遍历其他元素。

基础代码模板:

一般采用递归的方式写,没有太具体的模板,只能时多练习,画出决策树。

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值