【问题标题】:What is this O(N*k) sorting algorithm?这个 O(N*k) 排序算法是什么?
【发布时间】:2012-01-26 15:22:15
【问题描述】:

在处理“The fastest sort for BrainF***"”时,我发现了这个算法,它是 O(N*k),其中 k 是输入中的最大值。它需要 O(N) 额外的存储空间。

物理类比是你有 N 叠代币。堆栈的高度表示要排序的值。 (每个令牌代表一个位)。为另外 N 个堆栈留出空间。您从每个有标记的堆栈顶部取出一个标记,然后从右到左将一个标记添加到新组中的每个堆栈中,直到您的手为空。重复直到所有原始堆栈都为空。现在新集合从左到右升序排序

在 C 中:

 void sort(int A[], int N)
 {
    int *R = calloc(N,sizeof(int));
    do {
      int i,count=0; 
      for (i=0;i<N;i++) if A[i] { count++; A[i]--;}
      for (i=0;i<count;i++) R[i]++;
    } while (count);
    memcpy(A,R,N);  //A is now sorted descending.
    free(R);
 }

这个算法有名字吗?看起来和Bead Sort很像,但我觉得不太一样。

【问题讨论】:

  • 理解了代码才理解类比是不是很糟糕? ;-) 我主要是因为您要分类的不是硬币而是硬币数量所代表的数字这一事实使我感到困惑。因此,只要有相同数量的相同大小的硬币堆,一枚硬币最终放在哪个堆中并不重要。但不知道这种类型叫什么,但听起来肯定应该有一个名字。 ;-)
  • 试图更新解释。 (当我开始使用其他网站上的代码时,它对计数排序感到困惑 - 我赢不了:)
  • 这是一个非常有趣的问题。我会说这是一个珠子排序,除了维基百科页面说它是 O(n^2) 空间复杂度。我找不到一个简单的珠排序实现来正确比较它。 :)
  • 维基百科关于算法和数据结构的陈述最好持保留态度。我怀疑,但我懒得证明,一个只是另一个更节省空间的转换。

标签: algorithm sorting identify


【解决方案1】:

事实证明我并没有太懒惰。这是珠排序。这是original paper 的定义(PDF 链接):

考虑一组 A n 个正整数。 . . 对于 A 中的所有 a,从第一个杆到 a 沿杆滴下 a 珠(每杆一个珠) 的第一个杆。最后,逐级查看的珠子,从第n层到第一层,按升序表示A。

此实现以两种方式转换该算法:

  1. 反映它在y=x 中工作的“框架”。这会改变结果,使得每列中的“珠子”数量代表按降序排序的输出。在原始算法中,每行中“珠子”的数量表示按升序排序的输出。
  2. 与其将“帧”表示为布尔值的二维数组,不如将其表示为整数的一维数组。阵列中的每个槽对应一个“棒”,其值表示该棒上的珠子数量。这第二位是一种自然的转变——它只是承认,由于“珠子”不能漂浮在半空中,只记​​录杆上珠子的数量就可以告诉我们所有关于它们是如何排列在上面的信息。您可以通过增加相应的数字来将珠子放在杆上。

以下是对第一点的一些说明,直接取自论文第二页上的图表:由于算法最初是实现的,数组 [3, 2, 4, 2] 将由如下所示的网格表示:

* * *
* *
* * * *
* *

让珠子掉落会产生:

* *
* *
* * *
* * * *

然后,您必须从上到下读取行以获取输出:[2, 2, 3, 4]。而在按降序给出结果的版本中,您实际上是在这样做:

  *          *
  *   *      * *
* * * *  ->  * * * *
* * * *      * * * *

【讨论】:

  • 我好像很擅长重新发明别人的算法……谢谢分析。
  • 从 2-D 到 1-D 的转换将空间需求从 N*k 减少到 N,这似乎是一个不错的胜利。
  • 是的。令我印象深刻的是,这篇论文不厌其烦地详细介绍了模拟和数字硬件的实现,以及使用元胞自动机的版本(我猜这是 是 2002 年的),但并没有为更直接的程序化而烦恼实施。
  • 啊,我想我现在明白为什么维基百科说它是 n^2 空间了。我很高兴有人能够确认。 ;-)
  • 想多了,可能比O(Nk)还差。它运行外部循环 k 次,内部循环执行 N 次比较,然后最多写入 k 次。这使它更像顺序 (kmax(N,k))。虽然很简单,但速度并不快。
【解决方案2】:

我知道基数排序是 O(n*K) 复杂度中的一个代表。

http://en.wikipedia.org/wiki/Radix_sort

【讨论】:

  • 我认为这两个没有太多共同点
猜你喜欢
  • 2020-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-11
  • 1970-01-01
  • 2020-11-16
  • 2020-01-23
  • 2020-06-06
相关资源
最近更新 更多