对包含a-z和空格的单词数组进行排序的最快方法是什么?

时间:2012-10-28 14:57:02

标签: algorithm sorting

我想知道是否有一种比quicksort / mergesort更快的方式来排序这样的数组。

最大数组长度为10 ^ 6。 单词的长度为> = 10且< = 100,单词可以包含a-z和空格(总共27个不同的字符)。 字符中的字符不是唯一的(它们可以重复)。 数组中的所有单词都相同。

5 个答案:

答案 0 :(得分:7)

您可以将所有字词放在trie(或radix tree)中,然后以DFS顺序打印,从每个级别的“较小”词典字母开始在DFS。

此解决方案为O(n* |S|),其中|S|是字符串的平均长度。

简单示例:

让字符串集为[ac,ab,aca]

由此产生的特里将是:

         a
       /  \
      /    \
     b      c
     |     / \
     $    $   a
              |
              $

和DFS(更喜欢字典缩写字符):DFS将从a开始,转到b,然后到结束标志($)并将首先打印ab,然后返回a,然后转到c,然后转到下一个$,并打印ac,然后在{{旁边1}}及其a并将打印$,从而导致打印:

aca

被驱逐。

答案 1 :(得分:1)

任何基于比较的排序的下限是O(nlog(n))。您不能使用任何基于比较元素的排序算法,这些算法在低于此限制的最坏情况下运行。

合并排序和堆排序的最坏情况是运行时间为O(nlog(n))... 快速排序的最坏情况是运行时间为O(n ^ 2),但平均运行时间为O(n ^ log(n))。

值得一提的是,尽管快速排序的运行时间最短,为O(N ^ 2),但由于运行时间较短(如heaps(n)(n)(n)运行时间),因此它有时会因其他算法而失败。在当前机器架构上有效执行的常数因素和适用性。

线性排序算法,允许在非比较基础上以线性时间O(n)对整数(但不仅限于它们)进行排序(例如:计数排序,桶排序和基数排序)

MSD基数排序可以使用字典的数字顺序(在本例中为字符)和从左到右对字符串进行排序。

它首先使用最左边的字符使用另一个线性排序算法(比如桶排序)对所有字符串进行排序,然后使用左边的字符再次对它们进行排序,依此类推,直到它们按最右边的字符排序。 最后,数组将完全排序。

该算法将具有O(k * N)的运行时间,其中N是元素的数量,并且k是平均密钥长度(在这种情况下,字长度将> = 10&&< ; = 100)

答案 2 :(得分:1)

好吧,我已经阅读了(并且已经投票)关于基数排序和基数特里的答案,非常有用。 但是,
在基数排序的情况下 - 您需要进行91次N个元素的传递,因此它将 91 * N 。我不是在谈论额外的空间 在mergesort的情况下,你有 N * log N 比较,并且由于log N = log 1000000~20,你得到 20 * N 比较。

哪一个更快? :) 或者我可能在某个地方弄错了?

答案 3 :(得分:0)

可以计算ascii值,因此基本上这是一个整数排序。基于比较的排序例程最多可以获得O(n lg n) - 合并排序(创建另外两个大小为n / 2的数组所需的额外空间)或最坏的O(n ^ 2)(插入排序,快速排序,但是他们没有额外的空间复杂性)。这些渐近地比线性排序算法慢。我建议查看CLRS(http://www.amazon.com/Introduction-Algorithms-Thomas-H-Cormen/dp/0262033844)。关于线性时间排序的章节。在这种情况下,O(n)可能是你能做的最好的。此外,这篇文章可能有所帮助。 Sorting in linear time?

我查看基数排序。 http://en.wikipedia.org/wiki/Radix_sort

答案 4 :(得分:0)

为什么不是每三个字符的分布排序:需要19683(27 * 27 * 27)个元素的计数存储,这应该是可行的,然后最多需要34次传递。

但很快,每个键的子列表(三个字符的倍数)将足够短,以便对字符串的剩余部分使用插入排序或类似。 1.000.000 /(27 ^ 3)约为50

如果它们具有共同的长前缀,则相同的机制可以用于较长的密钥,即前30个字符将仅在20或30个子列表中划分列表。那么你不是把数字表示为数字,而是将它们表示为字符串,并将它们存储在一个字典中,这个速度较慢,但​​是需要较少的传递,也可能是较少的内存。此外,还需要N * log(M)查找,其中M是binairy树中不同键的数量,但散列也是可能的。