Union-Find 动态连通性
动态连通性是计算机的一种数据结构,动态维护结构中相互链接的组信息。
通俗的说 : 就像朋友圈,在社交网络中,彼此熟悉的人与人之间组成的朋友圈,但是这个圈子是会逐渐扩大的,不一定是你扩大,有可能你的朋友认识了一个新的朋友,或者 “断袖” 了,这种变化是动态的,然而这个关系网是庞大的,连通的,这就是动态连通数据结构。
假设:我与用户A相识, 用户A 与 用户 B 相识,那么就会默认为我与用户B 可能是相识,所以是连接起来一个组别,我就可以看到用户B的信息,计算机网络中也大致如此。
计算机语言描述
给定一个整数队 [ A , B],如果A ,B尚未相连,则使二者相连(红娘介绍对象),A,B相识后,我们可以称 A,B同是一组内的。
当A ,B 互通,以下关系是可以成立的:
- 自反性:AB自身是相连的
- 对称性:如果AB相连,那么BA也是相连
- 传递性:如果AB相连,BC相连,那么AC也是相连的
在一个圈子中,假设圈子容量是 N ,则可以定义一个从 0 到 N-1的整数队列表,A B是其中的值。然后进行如下操作
- 断定A和B是否相连 bool
- 如果AB已经相连,则没操作,未相连,则连接,并且归纳组
- 查找A或B属于那个组(圈子)
- Connected: 判断AB是否相互连接,同一组则相连。
- Union: 如果AB没有连接,则连接AB,并且归纳组,反正不处理
- Find: 查找AB所属圈子(组)
- Count: 组的数量
图 1.5.2
public class UnionInfo
{
private int _group;
private int _index;
public int Group { get => _group; set => _group = value; }
public int Index { get => _index; set => _index = value; }
}
public class Union_Find
{
public List<UnionInfo> bytes_datas;
public Union_Find(List<UnionInfo> init_Data)
{
bytes_datas = init_Data;
}
public Union_Find() { }
public void AddPend(UnionInfo _temp)
{
if (bytes_datas == null) bytes_datas = new List<UnionInfo>();
bytes_datas.Add(_temp);
}
public bool Connected(UnionInfo p, UnionInfo q)
{
if (p == null || q == null) throw new Exception("p or q is null");
return p.Group == q.Group;
}
public UnionInfo Find(int by_index)
{
return bytes_datas[by_index];
}
public UnionInfo Find(UnionInfo p)
{
int by_index = p.Index;
return Find(by_index);
}
public void Union(int by_index_p, int by_index_q)
{
UnionInfo p = Find(by_index_p);
UnionInfo q = Find(by_index_q);
int group = p.Group;
if (!Connected(p, q))
{
List<UnionInfo>.Enumerator _union = bytes_datas.GetEnumerator();
while (_union.MoveNext())
{
if (_union.Current.Group == group)
{
_union.Current.Group = q.Group;//修改组别
}
}
}
}
}
Test Code
public class Program
{
static void Main(string[] args)
{
Union_Find un = new Union_Find();
for (int i = 0; i < 10; i++)
{
UnionInfo _tempInfo = new UnionInfo();
_tempInfo.Group = i;
_tempInfo.Index = i;
un.AddPend(_tempInfo);
}
List<int[]> list = new List<int[]>()
{
new int[]{ 4,3},
new int[]{ 3,8},
new int[]{ 6,5},
new int[]{ 9,4},
new int[]{ 2,1},
new int[]{ 5,0},
new int[]{ 7,2},
new int[]{ 6,1}
};
object[] arg = new object[un.bytes_datas.Count];
foreach (int[] k in list)
{
UnionInfo p = un.Find(k[0]);
UnionInfo q = un.Find(k[1]);
un.Union(k[0], k[1]);
Console.WriteLine("{0} and {1} connected ? " + un.Connected(p, q), p.Index, q.Index);
}
for (int i = 0; i < un.bytes_datas.Count; i++)
{
arg[i] = un.bytes_datas[i].Group;
}
string str = "Final group list is ";
Console.WriteLine(str + String.Join(" ", arg));
}
}
Run Result
[1.] 图1.5.2取自 《算法4》