最好的连续排序算法?

时间:2009-07-19 18:45:12

标签: algorithm sorting

我有一组双精度数据,我需要总是对它们的列表进行排序。在添加数据时对数据进行排序的最佳算法是什么?

最好我的意思是数据计数中的Big-O最少,数据计数中的Small-O(最差情况),以及所需空间中的最小Small-O,如果可能的话,按顺序排列。

设置大小实际上是可变的,从少量(30)到大量数据(+ 10M)。

9 个答案:

答案 0 :(得分:28)

构建像red-black treeAVL tree这样的自平衡二叉树将允许Θ(lg n)插入和移除,以及按排序顺序检索所有元素的Θ(n)深度优先遍历),具有Θ(n)内存使用。实现有点复杂,但它们很有效,并且大多数语言都有库实现,因此在大多数情况下它们是首选。

此外,可以通过使用其下方的节点总数来注释树中的每个边(或等效地,节点)来完成对第i个元素的检索。然后可以在Θ(lg n)时间和Θ(1)空间中找到第i个元素,例如:

node *find_index(node *root, int i) {
  while (node) {
    if (i == root->left_count)
      return root;
    else if (i < root->left_count)
      root = root->left;
    else {
      i -= root->left_count + 1;
      root = root->right;
    }
  }
  return NULL; // i > number of nodes
}

支持这一点的实现可以在debian的libavl中找到;遗憾的是,维护者的网站似乎已关闭,但可以从debian's servers检索。

答案 1 :(得分:4)

used for indexes of database programs的结构是B +树。它是一种平衡的n-ary树。

From Wikipedia

对于具有h级索引的b阶B +树:

  • 存储的最大记录数为n = b ^ h
  • 最小键数为2(b / 2)^(h-1)
  • 存储树所需的空间是O(n)
  • 在最坏的情况下插入记录需要O(log-b(n))操作
  • 在最坏的情况下找到记录需要O(log-b(n))操作
  • 删除(以前定位的)记录需要在最坏的情况下进行O(log-b(n))操作
  • 在最坏的情况下,执行范围内出现k个元素的范围查询需要O(log-b(n + k))运算。

我在我的程序中使用它。您可以将数据添加到结构中,并始终按顺序,从前到后或从后到前遍历,或快速搜索任何值。如果找不到该值,则可以使用插入点添加值。

您可以通过使用b(桶的大小)来优化程序的结构。

关于B +树的有趣演示:Tree-Structured Indexes

你可以get the entire code in C++


编辑:现在我看到你的评论,你需要知道“集合中的第i个排序元素”是一个重要的。突然间,这使得许多数据结构不够理想。

最好使用SortedList,甚至更好的SortedDictionary。请参阅文章:Squeezing more performance from SortedList。两个结构都有一个GetKey函数,它将返回第i个元素。

答案 2 :(得分:2)

可能heap sort.堆只有O(log N)才能添加新数据,您可以在O(N log N)时间内随时弹出净结果。

如果你总是需要每次排序整个列表,那么除了insertion sort.之外没有其他选项可能很多O(N ^ 2)虽然你可以制作linked skip lists的巨大麻烦它O(N log N)。

答案 3 :(得分:2)

我会使用堆/优先级队列。最坏的情况与运行时的平均情况相同。下一个元素可以在O(log n)时间内找到。

我从Here is a templatized C# implementation派生的

this code

答案 4 :(得分:2)

好的,您希望对数据进行排序,但需要通过索引号提取数据。

从一棵基本的树开始,比如上面提到的红黑树。

修改树算法,以便在插入和删除过程中遇到的所有节点向树中插入元素时,保留每个分支下元素数的计数。

然后,当您从树中提取数据时,您可以随时计算索引,并根据是否大于或小于您要提取的索引来了解要采用的分支。

另一个考虑因素。使用动态内存分配的树中的10M元素+会吸收大量内存开销。即,指针可能占用比实际数据更多的空间,以及用于实现数据结构的其他任何成员。这将导致严重的内存碎片,并且在最坏的情况下会降低系统的整体性能。 (从虚拟内存中来回转换数据。)您可能需要考虑实现块和动态内存分配的组合。在某种情况下,您将树排序为数据块,从而减少内存开销。

答案 5 :(得分:2)

如果您只需要知道评论中所述的第i个最小元素,请使用以作者姓氏命名的BFPRT算法:Blum,Floyd,Pratt,Rivest和Tarjan,并且通常同意是同一篇论文中最重要的大型计算机科学大脑。 O(n)最坏情况。

答案 6 :(得分:1)

查看维基百科中的comparison排序算法。

答案 7 :(得分:1)

Randomized Jumplists也很有趣。 它们需要更少的空间作为BST和跳过列表。 插入和删除是O(log n)

答案 8 :(得分:0)

通过“一组双数据”,你的意思是一组实值数字吗?其中一个比较常用的算法是heap sort,我会检查出来。它的大部分操作都是O(n * log(n)),这是非常好的,但不符合你的所有标准。 heapsort的优点在于,您自己编写代码相当简单,而且许多语言都提供了管理已排序堆的库。