【问题标题】:Best way to join and sort small-ish, already sorted lists into one big list?将已排序的小型列表加入和排序到一个大列表中的最佳方法?
【发布时间】:2016-04-29 06:58:59
【问题描述】:

我有一个排序对象的列表(数组,不是链表)。这不是一个很长的列表:从 3 到 20 个元素不等,尽管大多数时候它可能会在较短的一端。此列表和所有其他列表将来自 HTTP 请求。将有大约 30-50 个请求,每个请求产生一个包含相同数量元素的数组。我的代码现在的工作方式是请求是同步的。我意识到这效率不高,并且可能很快会更改为一些多线程,但目前我仍处于初始阶段。将所有这些数组连接成一个大的排序数组的最佳方法是什么?会是因为每个数组都是从请求中返回并附加到结果数组中的吗?或者可能在所有请求完成后进行排序?既然没有那么多元素,相对来说,这还重要吗?多线程会对解决方案产生影响吗?

我不确定数组所持有的值是否相似是否会有所不同。例如: [100,200,300], [99, 105, 290], [115,215, 280]

【问题讨论】:

  • 要排序的数字是不是在某个比较小的范围内?
  • 根据您给出的约束,在最坏的情况下,当所有请求都完成时,最多有 (20 x 50) 个元素。这是 1000 个元素。我想说的是,在合并列表时不要进行任何比较和全部,只需合并所有数组并在最后进行排序。

标签: arrays multithreading algorithm list sorting


【解决方案1】:

将多个排序列表合并为一个列表的最快方法是执行k-way merge

从一个空的优先级队列开始,如果您按升序排序,通常是一个最小堆,然后将每个列表中的第一项推送到堆上。您存储在堆中的结构必须具有值(即数字)以及对它来自的列表的引用。那么:

  1. 从堆中弹出第一项并将其值添加到您的输出中。
  2. 从列表中取出包含您刚刚从堆中弹出的项的下一项,并将其添加到堆中。
  3. 继续直到堆为空。

简而言之,最小堆总是从每个列表中获取一个项目,并且这些项目中最低的项目始终是堆上的第一项。由于单个列表是按顺序排列的,这保证了堆顶部的项始终是所有列表中最小的剩余项,因此它是下一个输出的项。

【讨论】:

    【解决方案2】:

    有一些明智的方法可以尝试,然后衡量相对性能。

    由于要排序的元素数量较少,与算法的渐近复杂度相比,排序算法实现中的常数因素对整体性能的影响相对较大。

    我会将所有单独的范围收集到一个数组中,并在所有请求完成后对其进行排序;这将在您进行排序时使数组在缓存中保持热状态,而不是将许多排序与随机的其他处理交错。

    如果要排序的数字在小范围内,则通过计数排序进行排序;所需的额外O(n) 内存应该不是问题,因为n 最多为1000。

    否则,由于序列由多个排序范围组成,插入排序可能会执行良好,内部循环预计不会循环多次,当它循环时,内部条件应该具有良好的分支预测特性。

    话虽如此,对于这么少的元素,很可能你选择什么方法都没有关系,所以只需将所有元素收集在一个数组中并使用系统的库排序功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-28
      • 1970-01-01
      • 2013-06-28
      • 2013-11-10
      • 2023-03-25
      • 2012-06-14
      相关资源
      最近更新 更多