資料結構 — 並查集的原理與應用
並查集的原理與應用
並查集是一種樹型的資料機構,常用於處理一些不相交集合的合併及查詢問題.並查集是一種簡單的資料結構主要涉及兩個基本操作:
1.合併兩個不相交的集合.
2.判斷兩個元素是否屬於同一個集合.
並查集的實現原理:
首先並查集會開闢出一個陣列,假設陣列有10個人,那麼就會開闢10個大小的陣列,然後每一個下標代表一個人.陣列每一個節點的值
都為-1.表示每一個節點都是相對應的一個集合.大家都不相交.這個時候開始新增關係.如下圖:
所以我們發現現在確定一共有幾個集合,還有查詢兩個資料在不在一個集合當中就很容易了. 首先確定幾個集合你只需要便利一遍,
如果那個下標的值小於0,那麼就是一個集合.然後判斷兩個資料是不是在同一個集合裡面也很簡單. 分別找兩個資料的根.如果根
相同那麼他兩個就在一個集合裡,反之就不在.好了現在思想確定了,那麼我們過來實現程式碼.
class UnionFind
{
public:
UnionFind(int n)
{
_UnionTable.resize(n+1); //因為一般0號下標沒有用,所以多開出來一個空間.
for (int i = 0; i < n+1; ++i)
{
_UnionTable[i] = -1;
}
}
void AddUnion(int i,int j)
{
if (_UnionTable[i] < 0 && _UnionTable[j] < 0)
{
_UnionTable[i] += _UnionTable[j];
_UnionTable[j] = i;
}
else
{
int k = FindRoot(i);
int l = FindRoot(j);
_UnionTable[k] += _UnionTable[l];
_UnionTable[l] = k;
}
}
int FindRoot(int i)
{
assert(i >= 0);
int k = i;
while (_UnionTable[k] >= 0)
{
k = _UnionTable[k];
}
return k;
}
int size()
{
int count = 0;
for (int i = 0; i < _UnionTable.size(); ++i)
{
if (_UnionTable[i] < 0)
{
++count;
}
}
return count - 1;
}
private:
vector<int> _UnionTable;
};
這個程式碼就是實現一個最簡易的並查集,可以用它解決一點實際問題,比如當年小米的一道面試題! 40分啊! 好看題:
假設一組有N個人和M對好友關係(存於陣列R).如果兩個人是直接或者間接好友(好友的好友就是間接好友),則認為他們屬於同一個朋
友圈,請寫出程序求出這個N個人裡面一共有多少個朋友圈.
例如:N =5,M =3,R = {{1,2},{2,3},{4,5}} 表示有5個人,1和2是還有,2和3是好友,4和5是好友,則1,2,3屬於一個朋友圈,4,5
屬於一個朋友圈. 則一共擁有兩個朋友圈. 函式原型 : int friends(int m,int n,int* r[]);
首先拿到這個題我在不知道並查集這個資料結構之前是真的一頭霧水,用其他資料結構真的很難解決.但是使用並查集輕而易舉就解決
掉了,不相信? 我下面利用並查集演示解決該題:
class UnionFind
{
public:
UnionFind(int n)
{
_UnionTable.resize(n+1); //因為一般0號下標沒有用,所以多開出來一個空間.
for (int i = 0; i < n+1; ++i)
{
_UnionTable[i] = -1;
}
}
void AddUnion(int i,int j)
{
if (_UnionTable[i] < 0 && _UnionTable[j] < 0)
{
_UnionTable[i] += _UnionTable[j];
_UnionTable[j] = i;
}
else
{
int k = FindRoot(i);
int l = FindRoot(j);
_UnionTable[k] += _UnionTable[l];
_UnionTable[l] = k;
}
}
int FindRoot(int i)
{
assert(i >= 0);
int k = i;
while (_UnionTable[k] >= 0)
{
k = _UnionTable[k];
}
return k;
}
int size()
{
int count = 0;
for (int i = 0; i < _UnionTable.size(); ++i)
{
if (_UnionTable[i] < 0)
{
++count;
}
}
return count - 1;
}
private:
vector<int> _UnionTable;
};
int Friends(int m,int n,int a[][2])
{
UnionFind T(m);
for (int i = 0; i < n; i++)
{
T.AddUnion(a[i][0],a[i][1]);
}
return T.size();
}
void Test()
{
int n = 5;
int a[][2] = { { 1, 2 }, { 2, 3 }, { 4, 5 } };
cout << "一共有"<<Friends(5, 3, a)<<"個朋友圈"<<endl;
}
相關文章
- 資料結構-並查集資料結構並查集
- 資料結構之Kruskal演算法(並查集的應用)資料結構演算法並查集
- 資料結構之並查集資料結構並查集
- 演算法與資料結構之並查集演算法資料結構並查集
- 優雅的資料結構–並查集資料結構並查集
- 【資料結構】帶權並查集資料結構並查集
- 資料結構:速通並查集資料結構並查集
- 並查集應用總結並查集
- 資料結構——並查集 學習筆記資料結構並查集筆記
- 並查集詳解與應用並查集
- 並查集的應用並查集
- 並查集是一種怎樣的資料結構?並查集資料結構
- 並查集應用並查集
- 並查集—應用並查集
- 並查集的應用2並查集
- 資料結構與演算法知識點總結(3)樹、圖與並查集資料結構演算法並查集
- 並查集深度應用並查集
- 並查集以及應用並查集
- 並查集的簡單應用並查集
- 並查集的分析及應用並查集
- 並查集(二)並查集的演算法應用案例上並查集演算法
- 並查集的應用:hdu 1213並查集
- 社交網路 (並查集的應用)並查集
- Redis的資料結構與應用場景Redis資料結構
- 並查集擴充套件應用並查集套件
- 並查集的理解與實現總結並查集
- 食物鏈(並查集的簡單應用)並查集
- JavaScript資料結構——集合的實現與應用JavaScript資料結構
- 並查集經典應用場景並查集
- 【學習筆記】並查集應用筆記並查集
- 並查集的初級應用及進階並查集
- 並查集(Union-Find) 應用舉例並查集
- 【帶權並查集】理論和應用並查集
- 並查集 (Union-Find Sets)及其應用並查集
- 並查集在實際問題中的應用並查集
- 資料結構_連結串列的原理與應用1_單連結串列(基於C語言實現)資料結構C語言
- 【資料結構】——堆及其應用資料結構
- 大資料技術原理與應用大資料