【问题标题】:Recursive merge sort - sorts coordinates in ascending order from an origin递归合并排序 - 从原点按升序对坐标进行排序
【发布时间】:2021-07-12 06:05:14
【问题描述】:

我有一个任务,我需要实现合并排序以从原点按升序对一些坐标进行排序。我的程序坐标如下(无法编辑;它是分配所必需的):

// stores the origin (does not change).
struct origin
{
  int x_naught;
  int y_naught;
};

// Individual coordinate to be sorted. 
struct coordinate
{
  int x;
  int y;
};

我有一个未排序的结构坐标数组:struct coordinate **coordArray;,其中包含 n 个坐标结构指针。

我的问题是,使用归并排序从原点升序对这些坐标进行排序的最有效方法是什么?我最初计划有一个辅助函数,它声明一个单独的数组并将每个坐标的大小(距离公式)存储在coordArray 数组中,然后将该数组及其长度传递给递归合并排序函数。

我相信,这是最简单、最直接的方法。但是,我不喜欢这个辅助函数在调用 merge_sort 之前需要额外的 n(长度)个工作步骤来对 coordArray 进行排序。是否可以通过将两个结构指针传递到以某种方式对这些坐标进行排序一个递归的merge_sort函数?

可能的函数签名:

void merge_sort(struct origin *origin_coord, struct coordinate **coordArray, int length);

我在此处尝试实施的方法中看到的一个问题是如何处理分别对 x 和 y 分量进行排序(即 coordArray[I]->x, coordArray[I]->y) 用于 struct origin 中的 x 和 y (即 origin_coord->x_naught, origin_coord->y_naught).

我知道对于 merge_sort 和辅助函数来说,O(2n log(n))(或者甚至可能是 O(3nlogn) 将排序的幅度数组转换回其原始形式:(x, y))确实不是这很重要,但如果我要对 10 亿个坐标进行排序,那额外的 20 亿步工作可能很重要。

【问题讨论】:

  • 首先优化是翻译点,然后排序,然后翻译回来。换句话说,从所有x 值中减去x_naught,然后排序,然后将x_naught 添加到所有x 值中。 y 也一样。
  • 第二个优化是比较距离的平方,而不是距离。换句话说,不要费心求平方根。
  • 你已经掌握了通用的归并排序算法了吗?如果不是,我的建议是“忘记”性能部分以开始并实施简单的合并排序。一旦这样做了,您就可以开始考虑提高性能了。顺便说一句:对于距离公式,您不需要使用 sqrt - 只需比较平方距离。
  • 注意:O(2n log(n)) 与 O(n log(n)) 相同。

标签: c recursion coordinates mergesort


【解决方案1】:

如果您无法将距离或其平方存储在 coordinate 结构中,我建议您将原点结构作为参数传递给您的 mergesort_coords 函数,并在比较函数中重新计算两个距离的平方。与分配和处理辅助结构的开销相比,这种计算非常便宜。此外,时间复杂度在 O(N.log(N)) 不变。

关于xy 排序,您应该指定如何排序与原点距离相同的坐标。这有很多选项,但比较函数必须是传递的,并且顺序应该是完整的。

建议的原型:

void merge_sort(struct coordinate **coordArray, size_t count,
                int cmp(const struct coordinate *a,
                        const struct coordinate *b,
                        const struct origin *origin_coord),
                struct origin *origin_coord);

int cmpdistance(const struct coordinate *a,
                const struct coordinate *b,
                const struct origin *o)
{
    long long dxa = (long long)a->x - o->x_naught;
    long long dya = (long long)a->y - o->y_naught;
    long long dxb = (long long)b->x - o->x_naught;
    long long dyb = (long long)b->y - o->y_naught;
    long long da = dxa * dxa + dya * dya;
    long long db = dxb * dxb + dyb * dyb;
    if (da < db) return -1;
    if (da > db) return +1;
    // if points are at the same distance, order by x, then by y
    if (a->x < b->x) return -1;
    if (a->x > b->x) return +1;
    if (a->y < b->y) return -1;
    if (a->y > b->y) return +1;
    return 0;
}

【讨论】:

    猜你喜欢
    • 2021-08-30
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-30
    • 2019-07-23
    • 2021-11-06
    • 2019-01-22
    相关资源
    最近更新 更多