高级数据结构与算法 | 并查集(Union-Find)
文章目錄
- 并查集的原理
- 并查集的實現
- 例題
并查集的原理
在一些應用問題中,需要將n個不同的元素劃分成一些不相交的集合。開始時,每個元素自成一個
單元素集合,然后按一定的規律將歸于同一組元素的集合合并。在此過程中要反復用到查詢某一
個元素歸屬于那個集合的運算。適合于描述這類問題的抽象數據類型稱為并查集(union-find
set)。
并查集底層通常常用數組存儲,并且存在以下特性:
這里舉一個例子,假設今年秋季大一開學時班級共有10名學生,上海3人,海南4人,廣東3人。這些學生都是剛進入校園,彼此都不認識,一開始每一個學生都是一個獨立的小團體,現在用下標來為學生們編號,順序按照上面的所在地。
因為來自同一個地方的學生他們從小的風俗習慣都十分接近,并且也有共同話題,所以很快他們就形成了自己的小團體
緊接著,因為來自上海的2號同學和來自海南的5號同學是同一個宿舍的,所以他也很快融入了2號的朋友圈,并且把自己的朋友也介紹給2號,所以此時上海和海南的朋友圈集合開始交集
通過這個結構,可以確認此時存在著兩個集合,集合上海-海南共有7人,集合背景共有3人。
通過這種并查集的結構,可以用來解決以下問題
并查集的實現
class UnionFindSet { public://初始化時將所有元素置為-1,表示每一個都是獨立的集合UnionFindSet(size_t size): _ufs(size, -1),_rank(size, 1){}//找到某一個集合的根int FindRoot(int index){//根節點的值為負數,如果不為負則說明不是根節點,繼續找while (_ufs[index] >= 0){//因為每個節點存儲自己父節點的下標,所以往上繼續查找index = _ufs[index];}return index;}//將兩個集合并集bool Union(int x1, int x2){int root1 = FindRoot(x1);int root2 = FindRoot(x2);//本來就是一個集合,不需要合并if (root1 == root2){return false;}/*優化,讓小集合掛在大集合上,減少查詢次數if (_rank[root1] < _rank[root2 ]) {swap(root1 , root2);}_rank[root1] += _rank[root2];*///選擇root1作為根,將root2所在集合合并到root1中_ufs[root1] += _ufs[root2];//將另一個的父節點設置為root1_ufs[root2] = root1;return true;}//求集合的個數,即負節點的個數size_t count() const{size_t count = 0;for (auto it : _ufs){if (it < 0){count++;}}return count;}private:std::vector<int> _ufs;std::vector<int> _rank; //用于加速查找 };例題
并查集一般可以解決以下問題:
例如leetcode-547.朋友圈就屬于上面的第四種問題,也就是我最開始舉例的那個問題
leetcode-990. 等式方程的可滿足性就屬于上面的第二類問題
主要思路就是判斷不等集合是否與相等集合產生交集
總結
以上是生活随笔為你收集整理的高级数据结构与算法 | 并查集(Union-Find)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ STL : SGI-STL空间配
- 下一篇: 高级数据结构与算法 | LRU缓存机制(