【问题标题】:Why don't we update rank for disjoint set after path compression?为什么我们不更新路径压缩后不相交集的排名?
【发布时间】:2021-08-19 22:27:33
【问题描述】:

我已经为具有秩启发式和路径压缩的不相交集制作了一个模板。

template <typename T>
class disJSet
{
    map<T,T> parent;
    map<T,int> rank;
    public:
    //Linear time complexity 
    void makeSet(vector<T> it)
    {
        for(T i:it)
        {
            parent[i]=i;
            rank[i]=0;
        }
    }

    //Time complexity of O(log*n)
    T find(T el)
    {
        if(el!=parent[el])
            parent[el]=find(parent[el]);
        
        return parent[el];
    }

    //Time complexity of O(log*n)
    bool unionOp(T a,T b)
    {
        T a_id=find(a);
        T b_id=find(b);

        if(a_id==b_id)
            return false;

        if(rank[a_id]<rank[b_id])
            parent[a_id]=b_id;
        else
        {
            parent[b_id]=a_id;
            if(rank[a_id]==rank[b_id])
            {
                rank[b_id]=rank[b_id]+1;
            }
        }
        return true;    
    }
};

路径压缩在find() 方法中实现。为什么我们在路径压缩后不更新排名?

我的理由:每当有 find 调用时,每个中间节点都会因为路径压缩而成为叶子节点。并假设如果那是父级最长的子树,那么它的高度现在已经改变。但我们不会更新父/根节点的排名。

这可能会在联合操作中产生差异。例如,两个元素的联合将导致通过比较它们的等级来使一棵树成为另一棵树的孩子。但由于调用find(),排名可能无法代表树的最大高度。

【问题讨论】:

    标签: c++ algorithm time-complexity disjoint-sets


    【解决方案1】:

    无法在路径压缩后更新排名,因为到该根的其他路径可能比新路径长度长。

    并且您不需要在路径压缩后更新排名,因为它只需要表示路径长度上的一个上限

    【讨论】:

    • 是的,我明白了。我试着想反例,最后得出结论,我不需要在路径压缩后更新排名。由于排名启发式算法,树实际上是平衡的,并且仅单个分支上的路径压缩实际上不会降低树的高度。它可能会产生最多 1 的差异。尽管如果在驱动程序代码中显式调用 find(),这可能不是真的。
    猜你喜欢
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    • 2013-08-31
    • 1970-01-01
    • 2023-01-26
    • 1970-01-01
    • 2017-08-10
    相关资源
    最近更新 更多