并查集的优化
在上一节了解到并查集的快速查询,合并,判断归属组等操作,虽然这些操作都非常方便,但是在数据量较大的情况下,并查集的效率并不算高:
上一节中实现代码中使用的合并方法(merge,API设计中为union),每次合并都需要遍历全部元素的次数,而最少要合并N-1次才能将所有元素合并到同一组,因此我们要对其合并进行优化
为了提升union算法的性能,我们需要重新设计find方法和merge方法的实现,此时我们先需要对我们的之前数据结构中的groups数组的含义进行重新设定。
使用
优化查询分组which_group方法
- 我们仍然让groups数组的索引作为结点的元素
- groups[i]的值不再是当前结点所在的分组标识,而是当前结点的父结点,根据当前结点的父结点可以找到祖父结点,一直往上找,直到找到它的根结点,根结点则是其真正的分组
Python代码实现及测试
class UF_Tree:def __init__(self, n):self.num_groups = nself.groups = [i for i in range(n)]def count_groups(self):return self.num_groupsdef in_the_same_group(self, item1, item2):return self.which_group(item1) == self.which_group(item2)def which_group(self, item):"""Find item's root------>groups[groups[groups[...groups[item]...]]]"""while self.groups[item] != item:item = self.groups[item]return itemdef merge(self, item1, item2):if self.in_the_same_group(item1, item2):returnself.groups[self.which_group(item1)] = self.groups[self.which_group(item2)]self.num_groups -= 1if __name__ == '__main__':UF = UF_Tree(5)print(f"The initial number of groups is {UF.num_groups}")print(f"The initial number of groups is {UF.groups}")while True:p = int(input(f'Input the to-be-merge element: '))q = int(input(f"Merge to the target element's group: "))if UF.in_the_same_group(p, q):print(f"They are already in the same group")continueUF.merge(p, q)print(f"The number of groups now is {UF.count_groups()}")print(UF.groups)
运行结果
The initial number of groups is 5
The initial number of groups is [0, 1, 2, 3, 4]
Input the to-be-merge element: 0
Merge to the target element's group: 1
The number of groups now is 4
[1, 1, 2, 3, 4]
Input the to-be-merge element: 1
Merge to the target element's group: 2
The number of groups now is 3
[1, 2, 2, 3, 4]
Input the to-be-merge element: 2
Merge to the target element's group: 3
The number of groups now is 2
[1, 2, 3, 3, 4]
Input the to-be-merge element: 3
Merge to the target element's group: 4
The number of groups now is 1
[1, 2, 3, 4, 4]
Input the to-be-merge element:
可以寻找到item = 0的源分组为4