👋 Hi, I’m @Beast Cheng
👀 I’m interested in photography, hiking, landscape…
🌱 I’m currently learning python, javascript, kotlin…
📫 How to reach me --> 458290771@qq.com
喜欢《数据结构》部分笔记的小伙伴可以订阅专栏,今后还会不断更新。🧑💻
感兴趣的小伙伴可以点一下订阅、收藏、关注!🚀
谢谢大家!🙏
如何表示集合关系
逻辑结构——集合
将各个元素划分成若干个 互不相交 的子集
回顾:森林[[5.4.1 树的存储结构#^b13923]]
如何查到想要的元素?——从指定元素出发,一路向上,找到根结点
如何判断两个元素是否属于同一个集合?——分别查到两个元素的根,判断结点是否相同
如何把两个集合并为一个集合?——让其中一棵树成为另一棵树的孩子
应该采用什么样的存储结构?——双亲表示法更合适[[5.4.1 树的存储结构#双亲表示法(顺序存储)]]
“并查集”的基本操作
Find
——查:确定一个元素的所属集合
Union
——并:将两个不相交的集合合并为一个
注:并查集(Disjoint Set)是逻辑结构——集合的一种具体实现,只进行“并”和“查”两种基本操作
“并查集”的代码实现
// Find 查操作,找 x 的所属集合(返回 x 所属根结点)
int Find(int S[], int x){while (S[x] >= 0) // 循环寻找 x 的根x = S[x];return x; // 根的S[ ]小于 0
}
最坏时间复杂度: O ( n ) O(n) O(n)
// Union 并操作
void Union(int S[], int Root1, int Root2){// 要求Root1和Root2是不同的集合if(Root1 == Root2) return;// 将根 Root2 连到另一根 Root1下面S[Root2] = Root1;
}
时间复杂度: O ( 1 ) O(1) O(1)
“并查集”的优化
Union 操作的优化
优化思路:在每次 Union
构建树的时候,尽可能让树不长高
1. 用根结点的绝对值表示树的结点总数
2. Union 操作,让小树合并到大树
void Union(int S[], int Root1, int Root2){if(Root1 == Root2) return;if(S[Root2] > S[Root1]){ // Root1结点数更少S[Root1] += S[Root2]; // 累加结点总数S[Root2] = Root1; // 小树合并到大树}else{S[Root2] += S[Root1]; // 累加结点总数S[Root1] = Root2; // 小树合并到大树}
}
该方法构造的树的树高 不超过 l o g 2 n + 1 log_2n+1 log2n+1
Union
操作优化后,Find
操作最坏时间复杂度: O ( l o g 2 n ) O(log_2n) O(log2n)