已知统计分布数据的排序算法?

时间:2011-05-29 07:46:28

标签: algorithm performance sorting statistics complexity-theory

我刚刚想到,如果您对要排序的数据的分布(统​​计意义上)有所了解,那么如果您考虑这些信息,排序算法的性能可能会受益。

所以我的问题是,是否有任何排序算法考虑到这种信息?他们有多好?

编辑:一个澄清的例子:如果您知道数据的分布是高斯分布的,那么您可以在处理数据时动态估算平均值和平均值。这将为您估算每个数字的最终位置,您可以使用它来将它们放置在最终位置附近。

编辑#2:我很惊讶答案不是一个维基链接到一个讨论这个问题的页面。这不是一个很常见的情况(例如高斯情况)吗?

编辑#3:我正在为这个问题增加一笔赏金,因为我正在寻找明确的答案来源,而不是猜测。类似于“在高斯分布式数据的情况下,XYZ算法平均速度最快,正如Smith等人[1]所证实的那样”。但欢迎任何其他信息。

注意:我会将赏金奖励给得票最高的答案。明智地投票!

7 个答案:

答案 0 :(得分:33)

如果您要排序的数据具有已知分布,我会使用 Bucket Sort 算法。您可以为它添加一些额外的逻辑,以便您根据分布的属性计算各种桶的大小和/或位置(例如:对于Gaussian,您可能每个(sigma / k)远离均值,其中西格玛是分布的标准差。)

通过以这种方式获得已知分布并修改标准Bucket Sort算法,您可能会获得 Histogram Sort 算法或其附近的算法。当然,您的算法在计算上会比直方图排序算法更快,因为您可能不需要进行第一次传递(在链接中描述),因为您已经知道了分布。

编辑:根据您的问题的新标准,(虽然我之前的答案有关直方图排序链接到受人尊敬的NIST并包含效果信息),这是来自国际会议的同行评审期刊文章并行处理:

Adaptive Data Partition for Sorting Using Probability Distribution

作者声称这种算法比流行的快速排序算法具有更好的性能(高达30%)。

答案 1 :(得分:18)

听起来您可能想要阅读Self-Improving Algorithms:它们实现任意输入分发的最终预期运行时间。

  

我们提供这样的自我改进算法   对于两个问题:(i)排序a   数字序列和(ii)计算   Delaunay三角剖分的一个平面   点集。两种算法都实现   最佳预期限制复杂性。   算法从训练开始   他们收集的阶段   有关输入的信息   分布,然后是静止的   算法解决的制度   他们优化的化身。

如果您已经知道您的输入分布大致是高斯分布,那么在空间复杂度方面可能另一种方法会更有效,但就预期的运行时间而言,这是一个相当不错的结果。

答案 2 :(得分:6)

了解数据源分布,可以构建一个好的哈希函数。很好地了解分布,散列函数可能被证明是一个完美的散列函数,或者对于许多输入向量来说都接近完美。

这样的函数会将大小为n的输入分成n个区间,这样最小的项目将映射到第一个区域,最大的项目将映射到最后一个区域。当哈希是完美的 - 我们将实现排序只是将所有项目插入到箱子中。

将所有项目插入哈希表,然后按顺序提取它们将是哈希完美时的O(n)(假设哈希函数计算成本为O(1),并且下划线哈希数据结构操作为O (1))。

我会使用一组斐波那契堆来实现哈希表。

对于哈希函数不完美(但仍然接近完美)的输入向量,它仍然比O(nlogn)好得多。当它是完美的 - 它将是O(n)。我不确定如何计算平均复杂度,但如果被迫,我会打赌O(nloglogn)。

答案 3 :(得分:6)

计算机排序算法可分为 两类,基于比较的排序和 非基于比较的排序。以比较为基础 排序,其最佳表现的排序时间是 Ω(nlogn),而在最糟糕的情况下表现为 分拣时间可以上升到O(n2)。最近几年, 已经提出了一些改进的算法 加快基于比较的排序,例如高级 根据数据分布特征快速排序 。但是,这些的平均排序时间 算法只是Ω(nlog2n),并且只在最好的情况下 能达到O(n)。 与基于比较的排序不同, 基于非比较的排序,例如计数排序, 铲斗分拣和基数分拣主要取决于钥匙 和地址计算。当键的值是 有限范围从1到m,计算 非基于比较的排序的复杂性 O(M + N)。特别是,当m = O(n)时,排序时间 可以达到O(n)。但是,当m = n2,n3,......时, 无法获得线性排序时间的上限。 在非基于比较的排序中,桶排序 将具有相似键的一组记录分发到 适当的“桶”,然后另一种排序算法 应用于每个桶中的记录。带斗 排序时,将记录划分为m个桶的次数较少 耗费时间,而只有少数记录 包含在每个桶中,以便“清理排序” 算法可以非常快速地应用。因此, 桶分类有可能渐近保存 排序时间与Ω(nlogn)算法相比较。 显然,如何将所有记录统一分配到 铲斗在铲斗分拣中起着关键作用。因此,您需要的是一种构造哈希函数的方法 根据数据分布,用于 基于的统一分配n个记录到n个桶中 每条记录的关键。因此,分拣时间 提出的桶分类算法将达到O(n) 在任何情况下。

查看此论文:http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=5170434&tag=1

答案 4 :(得分:5)

Bucket sort会为您提供线性时间排序算法,只要您可以在O(1)时间内计算每个点的CDF。

您也可以在其他地方查找的算法如下:

a = array(0, n - 1, [])          // create an empty list for each bucket
for x in input:
  a[floor(n * cdf(x))].append(x) // O(1) time for each x
input.clear()
for i in {0,...,n - 1}:
  // this sorting step costs O(|a[i]|^2) time for each bucket
  // but most buckets are small and the cost is O(1) per bucket in expectation
  insertion_sort(a[i])
  input.concatenate(a[i])

运行时间是期望的O(n)因为期望有O(n)对(x,y)使得x和y落在同一个桶中,并且插入排序的运行时间恰好是O(同一桶中的n +#对)。分析类似于FKS static perfect hashing的分析。

编辑:如果你不知道分布,但是你知道它来自哪个家族,你可以通过计算均值和方差来估计O(n)中的分布,在高斯情况下,然后使用相同的算法(顺便说一下,在这种情况下计算cdf是非常重要的)。

答案 5 :(得分:4)

您可以在快速排序中使用该信息来选择枢轴值。我认为这会提高算法远离O(N ** 2)最坏情况复杂度的概率。

答案 6 :(得分:3)

我认为cycle sort属于这一类。当您知道希望每个元素最终到达的确切位置时,可以使用它。

  

Cyclesort有一些不错的属性 - 对于某些受限制的数据类型,它可以在线性时间内进行稳定的就地排序,同时保证每个元素最多移动一次。