问题描述
有若干数量的节点,如果A节点与B节点相连接,则表明A与B为同类节点,且满足传递性,求出有多少种类别的节点;针对大量节点的情况给出最优的解法
解决方案
算法第4版P136提到
将问题转化为类表示
- 用一个列表表示所有的节点n,其值表示节点的类别,初始化时为每个节点赋不同的值
- union函数将给定的两节点的标识符置为相同值,同时也要将这两个节点的同类节点置为该值,即将两类节点置为同一类
- find函数获取节点的标识符,即类别
- connected函数判断节点是否连通
- count函数计算类别数
如下
优化的关键在于find函数和union函数
quick-find算法
find函数直接返回标识符,union通过该标识符对列表全部扫描,修改标识符
试想一下,如果给出的节点量非常大,在每次执行union时都要进行整个列表的扫描,很显然是不可取的
quick-union算法
使用树,如果两个节点相连通,只需要将一节点的根节点作为到另一节点的根节点的子节点;不改变每个节点的标识符,只是修改其对应的根节点,这样每个节点存储的就是父节点的下标;只有根节点的下标等于其存储的值
union-find算法(加权quick-union算法)
上述quick-union算法的最坏的情况是:1号节点的父节点是2号,2号节点的父节点是3号,3号节点的父节点是4号,依次至最后,树的深度变为节点的个数,这样并没有降低查找的次数;针对于此,做如下改变:对于union函数每次在寻找到两个根节点后,判断其含有的节点个数,将小树的根节点添加到大树的根节点下面,就可以降低树的深度
这样需要为每个节点添加一个变量,代表以该节点为根节点组成树的节点数
完整代码如下: