Algorithm 联合查找算法如何与“联合查找”一起使用;“真正的”;数据

Algorithm 联合查找算法如何与“联合查找”一起使用;“真正的”;数据,algorithm,set,Algorithm,Set,在普林斯顿算法课程开始时,介绍了动态连通性问题(快速查找、快速联合)。下面是对它的描述: 输入是一个整数对序列,其中每个整数 表示某种类型的对象,我们将解释对pq 正如“p与q相连”的意思一样,我们假设“p与q相连”是 等价关系,这意味着它是 反身:p是 连接到p 对称:如果p连接到q,那么q是 连接到p 传递的:如果p与q相连,q是 连接到r,则p连接到r 它有一个简单的实现,叫做快速查找: 一种方法是保持p和q连通的不变量 当且仅当id[p]等于id[q]。换句话说,所有站点都在一个 组

在普林斯顿算法课程开始时,介绍了动态连通性问题(快速查找、快速联合)。下面是对它的描述:

输入是一个整数对序列,其中每个整数 表示某种类型的对象,我们将解释对pq 正如“p与q相连”的意思一样,我们假设“p与q相连”是 等价关系,这意味着它是

  • 反身:p是 连接到p
  • 对称:如果p连接到q,那么q是 连接到p
  • 传递的:如果p与q相连,q是 连接到r,则p连接到r
它有一个简单的实现,叫做
快速查找

一种方法是保持p和q连通的不变量 当且仅当id[p]等于id[q]。换句话说,所有站点都在一个 组件在id[]中必须具有相同的值。调用此方法 快速查找,因为find(p)只返回id[p],它会立即 表示连接的(p,q)仅减少到测试id[p]==id[q] 当且仅当p和q在同一个分量中时返回true…To 将这两个组件组合成一个,我们必须使所有id[] 两组站点对应的条目具有相同的值,如图所示 在右边的例子中

我的问题是如何将其用于真实对象?它适用于整数,但如果我需要知道对象
A
是否连接到对象
B
,而不是
3
连接到
5
,该怎么办?我能想到的一个解决方案是拥有一个对象数组,其中数组中每个对象的索引对应于用于连接的数组的索引。例如:

   1   2   3   4   5
[ { } { } {A} { } {B} ]   <---- real data

   1   2   3   4   5
[  1   2   3   4   3 ]    <---- connections (3 and 5 have the same group id 3)
12345
[{}{{}{}{{}{{B}]Short安瑟:是的

更详细的回答:您必须将真实对象映射到整数。 映射的方法之一是对两种类型的对象使用相同的表(如您所说)

大多数编程语言都有内置映射。例如C语言有“字典”类,C++有“map”类。
您也可以编写自己的映射。

您的建议肯定会奏效,但当对象列表以某种方式发生变化(例如,以不同方式排序)时,可能会成为一件麻烦事

通过使用所提到的
id
属性(或任何其他名称)扩展对象,可以实现所提到的
quick find
方法

例如,如果您有这些对象(使用Python语法):

a={“num”:1,“code”:“test”};
b={“num”:15,“code”:“house”};
c={“num”:9,“code”:“garden”};
d={“num”:4,“code”:“flower”};
e={“num”:24,“code”:“cat”};
然后将
id
属性添加到这些对象中(这种扩展的语法在许多语言中都不同):

a[“id”]=1#使用附加属性扩展对象。
b[“id”]=2
c[“id”]=3
d[“id”]=4
e[“id”]=3
然后创建一个函数,告诉您两个对象是否连接,如
快速查找所述:

def已连接(x,y):
返回x[“id”]==y[“id”];
在这种情况下,以下测试的结果为真:

print(连接(c,e));#真的
备选方案:保持连接分离 如果不想通过添加
id
属性来改变原始对象,可以创建单独的贴图。某些语言可以为每个对象提供唯一的标识符。例如,在Python中,可以使用内置的
id()
函数检索该标识符。如果不可用,您将使用对象的唯一属性,该属性在示例数据中为
num
属性。因此,在Python中:

conn = {}
conn[id(a)] = 1
conn[id(b)] = 2
conn[id(c)] = 3
conn[id(d)] = 4
conn[id(e)] = 3

def are_connected(x, y):
    return conn[id(x)] == conn[id(y)];

print (are_connected(c, e)); # True
快速联合算法 在这种方法中,您不会(总是)为连接的对象存储相同的id,而是让它们指向同一组连接对象中的另一个(子对象到父对象),树的根指向自身

如果需要测试两个对象是否连接,则可以找到它们各自连接的两个根(通过它们的祖先遍历到树的顶部),并查看它们是否共享该根

使用稍有不同的样本数据,并使用
id
属性,它将如下所示:

           a             c
           |            / \
           b           d   e
                      /
                     f
a={“num”:1,“code”:“test”};
b={“num”:15,“code”:“house”};
c={“num”:9,“code”:“garden”};
d={“num”:4,“code”:“flower”};
e={“num”:24,“code”:“cat”};
f={“num”:88,“code”:“dog”};
然后将
id
属性添加到这些对象中(这种扩展的语法在许多语言中都不同):

a[“id”]=a#它是根,所以是自引用
b[“id”]=a#与a相同的组
c[“id”]=c#不同树的根
d[“id”]=c#与c同一组
e[“id”]=c#与c同一组
f[“id”]=d#与c是同一组,但是d的子级
这可以这样表示:

           a             c
           |            / \
           b           d   e
                      /
                     f
告诉您两个对象是否连接的函数现在如下所示:

           a             c
           |            / \
           b           d   e
                      /
                     f
def已连接(x,y):
而x[“id”]!=x:#而不是根
x=x[“id”]#在树上向上走
而y[“id”]!=y:#y也一样
y=y[“id”]#在树上向上走
返回x==y;#如果根相同:则连接原始对象
请注意,您也可以将其编写为递归函数

在这种情况下,以下测试的结果为真:

print(是否连接(e,f))#真的
然后将id属性添加到这些对象中-谢谢,如何跟踪集合并加入它们?可以使用
quick find
实现并更新集合中所有对象的
id
,但这是低效的,因为它具有
O(n)
运行时复杂性。更好的实现
加权快速联合
,它与