前言
主要内容出自算法第四版,这里记录一些我的理解
问题描述
连通性就是判断两个事物是不是一伙的,是不是连在一起,就好像一个连在一起的铃铛,可不可以一次把全部都提留起来。 构建数据的过程就是把一个一个对象连起来,如果已经连起来了,就不用连了, 最后形成一幅无环连通图
应用
- 网络,判断是不是可达的,需不需要架设新的线路
- 变量相等
- 集合分类
解法
1. quick-find
顾名思义,就是 find 起来很快,union 很慢. 实现的方式用输入构建一个哈希表(key-value) table, 对于j 和 k两个如果 table[j] == table[k], 就认为 j 和 k 是联通的
# 以下代码均为实例代码
def find(key)
table[key]
end
def union(first_key, second_key)
first_value = find(first_key)
second_value = find(second_key)
if first_value != second_value
table.each do |k, v|
if v == first_value
table[k] = second_value
end
end
end
end
2. quick-union
利用链表,把所有的在一起的连起来。如果 对 p 和 q 做 union 的做作,就是把 p 所在树的根节点指向 q 所在树的根节点, 数据结构上也是用一个Hash Table, 根节点的 key value 是相等的,其他节点的 key 代表这个数据本身,value 代表他指向的节点
def find(key)
# 相当于找到这棵树的根节点来代表他, 相当于他们这个团体(set)的名字
compare_value = key
while compare_value != table[key]
compare_value = table[key]
end
compare_value
end
def union(first_key, second_key)
first_key_root = find(first_key)
second_key_root = find(second_key)
if first_key_root != second_key_root
table[first_key] = second_key_root
end
end
3. weighted quick-union (加权quick-union)
quick-union 明显的缺点是找的时候,如果树太高的话,找的这个点又是在树底下,要挨个找到根,非常浪费时间. 所以说怎么把书的高度降低就是关键了。这个时候就是刚才连树的时候,可以 a 往 b 连,也可以 b 往 a 连,那怎么选择呢,我们这次不按照传值传进来的顺序连,而是智能一点,总是把短的树往长的树连,这样子就是 weighted quick-union 啦,简单又好用 perfect!
class WeightedQuickUnion
# capacity 的读音是[ ke 'pan si ti] 注意重音位置
def initialize(capacity)
@set_count = capacity #不同的集团有几个,也就是所谓的连通分量
# 保存 x 在他所在集团成员数量
@single_set_count_table = (1..capacity).to_a.map {|x| [x, 1]}.to_h
#一开始大家全部都指向自己
@relation_table = (1..capacity).to_a.map {|x| [x, x]}.to_h
end
def addNode(first_node, second_node)
first_key_root = find(first_key)
second_key_root = find(second_key)
return if (first_key_root == second_key_root)
if @single_set_count_table[first_node] > @single_set_count_table[second_node]
@relation_table[second_node] = find(first_node)
@single_set_count_table[first_node] += single_set_count_table[second_node]
else
@relation_table[first_node] = find(sencond_node)
@single_set_count_table[second_node] += single_set_count_table[second_node]
end
@set_count--
end
def find(key)
# 跟 quick-union 是一样的
compare_value = key
while compare_value != table[key]
compare_value = table[key]
end
compare_value
end
end