并查集

作用:

判断两个节点 是否在一个集合内/是否联通

数据结构:

数组id,id[i] 表示第i个元素的父元素的位置


上图表示所有单数节点 和双数节点各在一个集合中

主要算法:

第一种算法(quick find):

抽象数据结构如下,特点是最多只有双层,任何元素的父元素都是该集合的根元素

查找父元素:

int find(int p) {
		return id[p];
	}

quick find 使用O(1)的时间复杂度来找到父节点,但是相应的,需要接近O(n)时间来执行Union操作 

union 操作:

bool unionElements(int p, int q) {
		int pId = find(p);
		int qId = find(q);
		if (pId == qId) {
			return;
		}
		else {
			for (int i = 0; i < count; i++) {
				if (id[i] == pId) {
					id[i] == qId;
				}
			}
		}
	}

上面的代码中,为其中一个集合中的所有元素重新指定父节点,所以时间复杂度较大

第二种算法(quick union):

抽象数据结构如下,可以有多层结构,层数由实际问题决定,


查找根元素:

int find(int p) {
		while (p != parent[p]) {
			p = parent[p];
		}
		return p;
	}

需要逐层向上查询父节点来找到根节点

union (quick union):

bool unionElements(int p, int q) {
		int pRoot = find(p);
		int qRoot = find(q);
		if (pRoot == qRoot) {
			return;
		}
		else {
			parent[pRoot] = qRoot;
		}
	}

union 的时间复杂度与层数有关,层数越大,find的时间复杂度就越大,同时union的时间复杂度也越大

优化:

基于第二种算法的优化,减少层数

方法一:基于rank的优化

简单说就是在每次union的时候,总是选择将高度小的那个集合连接到高度大的集合的根节点上,只有当两个集合层数相同时,union后的集合层数才会增加

实现方法:

为每个根元素维护rank数组,表示元素所在的集合的高度

方法二:路径压缩

在find操作时,将元素的父节点设置为元素的父节点的父节点,以此来减少路径长度(集合高度),在最极端情况下,可以将所有元素都连接到根元素上

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值