1.5.22

1.5.22 #

解答 #

平方级别算法在输入加倍后耗时应该增加四倍,线性则是两倍。

下面给出我电脑上的结果,数据量较大时比较明显:

N:16000
quick-find
平均次数:8452
用时:143 比值:4.46875

quick-union
平均次数:7325
用时:202 比值:3.25806451612903

weighted-quick-union
平均次数:6889
用时:1


N:32000
quick-find
平均次数:15747
用时:510 比值:3.56643356643357

quick-union
平均次数:15108
用时:801 比值:3.96534653465347

weighted-quick-union
平均次数:17575
用时:3 比值:3


N:64000
quick-find
平均次数:33116
用时:2069 比值:4.05686274509804

quick-union
平均次数:38608
用时:4635 比值:5.78651685393258

weighted-quick-union
平均次数:34850
用时:6 比值:2

代码 #

long lastTimeQuickFind = 0;
long lastTimeQuickUnion = 0;
long lastTimeWeightedQuickUnion = 0;
for (var n = 2000; n < 100000; n *= 2)
{
    Console.WriteLine("N:" + n);
    var quickFindUf = new QuickFindUf(n);
    var quickUnionUf = new QuickUnionUf(n);
    var weightedQuickUnionUf = new WeightedQuickUnionUf(n);

    // quick-find
    Console.WriteLine("quick-find");
    var nowTime = RunTest(quickFindUf);
    if (lastTimeQuickFind == 0)
    {
        Console.WriteLine("用时:" + nowTime);
        lastTimeQuickFind = nowTime;
    }
    else
    {
        Console.WriteLine("用时:" + nowTime + " 比值:" + (double)nowTime / lastTimeQuickFind);
        lastTimeQuickFind = nowTime;
    }

    Console.WriteLine();

    // quick-union
    Console.WriteLine("quick-union");
    nowTime = RunTest(quickUnionUf);
    if (lastTimeQuickUnion == 0)
    {
        Console.WriteLine("用时:" + nowTime);
        lastTimeQuickUnion = nowTime;
    }
    else
    {
        Console.WriteLine("用时:" + nowTime + " 比值:" + (double)nowTime / lastTimeQuickUnion);
        lastTimeQuickUnion = nowTime;
    }

    Console.WriteLine();

    // weighted-quick-union
    Console.WriteLine("weighted-quick-union");
    nowTime = RunTest(weightedQuickUnionUf);
    if (lastTimeWeightedQuickUnion == 0)
    {
        Console.WriteLine("用时:" + nowTime);
        lastTimeWeightedQuickUnion = nowTime;
    }
    else
    {
        Console.WriteLine("用时:" + nowTime + " 比值:" + (double)nowTime / lastTimeWeightedQuickUnion);
        lastTimeWeightedQuickUnion = nowTime;
    }

    Console.WriteLine();

    Console.WriteLine();
}

// 进行若干次随机试验,输出平均 union 次数,返回平均耗时。
static long RunTest(Uf uf)
{
    var timer = new Stopwatch();
    var total = 0;
    var repeatTime = 10;
    timer.Start();
    for (var i = 0; i < repeatTime; i++)
    {
        total += ErdosRenyi.Count(uf);
    }

    timer.Stop();
    Console.WriteLine("平均次数:" + total / repeatTime);

    return timer.ElapsedMilliseconds / repeatTime;
}

另请参阅 #

UnionFind 库