并查集是这样的数据结构:有一大堆的数据,把一些元素放在一个集合当中,另外一些元素放在另一个一个集合当中。
对于它的操作有:查看两个元素是否在一个集合当中、合并两个元素。 合并的时候采取的策略是这样的:将两个元素所在的集合的所有元素一起放入一个集合当中。
这里使用两个字典来实现并查集:一个字典保存当前节点的父节点的信息,另外一个保持父节点大小的信息。
class UnionFindSet(object): """并查集""" def __init__(self, data_list): """初始化两个字典,一个保存节点的父节点,另外一个保存父节点的大小 初始化的时候,将节点的父节点设为自身,size设为1""" self.father_dict = {} self.size_dict = {} for node in data_list: self.father_dict[node] = node self.size_dict[node] = 1 def find_head(self, node): """使用递归的方式来查找父节点 在查找父节点的时候,顺便把当前节点移动到父节点上面 这个操作算是一个优化 """ father = self.father_dict[node] if(node != father): father = self.find_head(father) self.father_dict[node] = father return father def is_same_set(self, node_a, node_b): """查看两个节点是不是在一个集合里面""" return self.find_head(node_a) == self.find_head(node_b) def union(self, node_a, node_b): """将两个集合合并在一起""" if node_a is None or node_b is None: return a_head = self.find_head(node_a) b_head = self.find_head(node_b) if(a_head != b_head): a_set_size = self.size_dict[a_head] b_set_size = self.size_dict[b_head] if(a_set_size >= b_set_size): self.father_dict[b_head] = a_head self.size_dict[a_head] = a_set_size + b_set_size else: self.father_dict[a_head] = b_head self.size_dict[b_head] = a_set_size + b_set_size if __name__ == '__main__': a = [1,2,3,4,5] union_find_set = UnionFindSet(a) union_find_set.union(1,2) union_find_set.union(3,5) union_find_set.union(3,1) print(union_find_set.is_same_set(2,5)) # True