2.4.28

2.4.28 #

解答 #

开始时让 N=10^5,在 M=10^4 不变的情况下令 N 不断翻倍,求出算法增长的数量级。

再根据求出的增长的数量级估计 N=10^8 时所需要的时间。

为了方便比较,需要编写一个欧几里得距离类,

构造时输入一个点的坐标,内部自动计算并保存这个点到原点的欧几里得距离。

欧几里得距离的计算公式如下:

$$ d(x,y)=\sqrt{\sum_{i=1}^{n}(x_i-y_i)^2} $$

其中,x 和 y 分别代表两个点。

在本题中,y 始终是原点,且使用三维坐标系,因此公式可以简化为:

$$ d=\sqrt {x^2+y^2+z^2} $$

同时这个类需要实现 IComparable 接口以作为最小堆的元素。

做测试时,先随机生成 N 个点,再建立一个最小堆。

随后开始计时,把开始的 m 个点插入。

剩余的 n-m 个点则是先删除最小值再插入,这样可以保证最小堆的大小不变。

最后再把堆中的所有元素输出,停止计时。

用不断倍增的的 N 值做上述测试,获得每次的耗时,进而求得算法增长的数量级。

求得的结果如下:

可以推出当 N=10^8 时耗时为 $ 398 \ ms × 1000 = 398 \ s $

代码 #

欧几里得距离类,EuclideanDistance3D

internal class EuclideanDistance3D : IComparable<EuclideanDistance3D>
{
    private readonly int _x, _y, _z;
    private readonly double _distance;

    /// <summary>
    /// 计算点到原点的欧几里得距离。
    /// </summary>
    /// <param name="x">x 轴坐标。</param>
    /// <param name="y">y 轴坐标。</param>
    /// <param name="z">z 轴坐标。</param>
    public EuclideanDistance3D(int x, int y, int z)
    {
        _x = x;
        _y = y;
        _z = z;
        _distance = Math.Sqrt(x * x + y * y + z * z);
    }

    /// <summary>
    /// 比较两个欧几里得距离的大小。
    /// </summary>
    /// <param name="other">另一个欧几里得距离。</param>
    /// <returns></returns>
    public int CompareTo(EuclideanDistance3D other)
    {
        return _distance.CompareTo(other._distance);
    }

    /// <summary>
    /// 以 "(x, y, z)" 形式输出点的坐标。
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return "(" + _x + ", " + _y + ", " + _z + ")";
    }
}

另请参阅 #

欧几里得距离-维基百科 PriorityQueue 库