1.5.20

1.5.20 #

解答 #

将 parent 数组和 size 数组用链表代替即可,很容易实现。

代码 #

修改后的 WeightedQuickUnionUF.cs

public class WeightedQuickUnionUf
{
    protected LinkedList<int> Parent;       // 记录各个结点的父级。
    protected LinkedList<int> Size;         // 记录各个树的大小。
    protected int Count;                    // 分量数目。

    /// <summary>
    /// 建立使用加权 quick-union 的并查集。
    /// </summary>
    public WeightedQuickUnionUf()
    {
        Parent = new LinkedList<int>();
        Size = new LinkedList<int>();
    }

    /// <summary>
    /// 获取 parent 数组。
    /// </summary>
    /// <returns>parent 数组。</returns>
    public LinkedList<int> GetParent()
    {
        return Parent;
    }

    /// <summary>
    /// 获取 size 数组。
    /// </summary>
    /// <returns>返回 size 数组。</returns>
    public LinkedList<int> GetSize()
    {
        return Size;
    }

    /// <summary>
    /// 在并查集中增加一个新的结点。
    /// </summary>
    /// <returns>新结点的下标。</returns>
    public int NewSite()
    {
        Parent.Insert(Parent.Size(), Parent.Size());
        Size.Insert(1, Size.Size());
        Count++;
        return Parent.Size() - 1;
    }

    /// <summary>
    /// 寻找一个结点所在的连通分量。
    /// </summary>
    /// <param name="p">需要寻找的结点。</param>
    /// <returns>该结点所属的连通分量。</returns>
    public int Find(int p)
    {
        Validate(p);
        while (p != Parent.Find(p))
        {
            p = Parent.Find(p);
        }
        return p;
    }

    /// <summary>
    /// 将两个结点所属的连通分量合并。
    /// </summary>
    /// <param name="p">需要合并的结点。</param>
    /// <param name="q">需要合并的另一个结点。</param>
    public void Union(int p, int q)
    {
        var rootP = Find(p);
        var rootQ = Find(q);
        if (rootP == rootQ)
        {
            return;
        }

        if (Size.Find(rootP) < Size.Find(rootQ))
        {
            Parent.Motify(rootP, rootQ);
            Size.Motify(rootQ, Size.Find(rootQ) + Size.Find(rootP));
        }
        else
        {
            Parent.Motify(rootQ, rootP);
            Size.Motify(rootP, Size.Find(rootQ) + Size.Find(rootP));
        }
        Count--;
    }

    /// <summary>
    /// 检查输入的 p 是否符合条件。
    /// </summary>
    /// <param name="p">输入的 p 值。</param>
    protected void Validate(int p)
    {
        var n = Parent.Size();
        if (p < 0 || p >= n)
        {
            throw new ArgumentException("index" + p + " is not between 0 and " + (n - 1));
        }
    }
}