使用字节比较对结构进行排序的最佳排序算法?

Posted

技术标签:

【中文标题】使用字节比较对结构进行排序的最佳排序算法?【英文标题】:Best sorting algorithm for sorting structs with byte comparisons? 【发布时间】:2011-01-23 17:25:57 【问题描述】:

我有一个包含 64 个结构的数组,其中包含大量数据(结构大约 128 个字节,因此需要重新排列 8192 个字节)。数组需要根据每个结构中的单个无符号字节进行排序。我的数据的一个有趣属性是,很可能会有很多重复的排序值——这意味着如果你去掉所有重复,数组可能只有 10 个唯一元素长,但这不是给定的。

排序后,我需要创建一个堆栈来存储每个唯一字节运行开始的大小和类型: 所以如果我最终得到排序值: 4,4,4,9,9,9,9,9,14,14 堆栈将是: (4,3), (9,5), (14,2)

我认为在这些条件下我可以执行一些不错的优化。如果我进行堆排序,我可以在排序时创建堆栈,但这会比 qsort 快,然后在后面构建堆栈吗?由于我使用的大型结构,任何排序算法会运行得更慢吗?由于我只比较字节,我可以进行任何优化吗?

顺便说一句:语言是 c++

谢谢。

【问题讨论】:

你会用什么做堆栈,自制的还是内置的? 我想要最快的,所以我想它会是一个使用固定缓冲区的简单自制的。 您需要实际排序还是只需要存储大小和类型的“堆栈”? 我需要对它们进行排序,但不稳定的排序也可以。 【参考方案1】:

我想 STL 会很好地做你想做的事。重新编写自己的排序例程和容器可能容易出错,而且速度很慢。所以只担心你是否发现它是一个瓶颈。

【讨论】:

我反对为此目的使用 std,因为我无法确定它的排序方式!我想使用最有效的实现,而不是通用的。不过,谢谢。 @Pepe:你甚至没有测量它们,但你基于直觉反对它? STL 例程通常非常非常好。就像我说的,如果你甚至没有测量它,那么你不应该担心它。 @Pepe:如果你想浪费你的时间,最终得到易碎的、难以阅读的、手写的容器和排序例程等,那么请成为我的客人!但这不是开发性能关键代码的好方法。 @Pepe 如果你还不知道如何做到这一点,那么你就不会打败 std。 @Pepe 如果你真的知道那你为什么要问?【参考方案2】:

通常对于大型对象,对对象的指针/索引数组进行排序比对对象进行排序更快。或者对节点数组进行排序,其中每个节点包含对象的指针/索引和对象的排序键(在这种情况下,键是一个字节)。要在 C++ 中执行此操作,您只需为 std::sortstd::stable_sort 提供一个合适的比较器。然后如果你需要原始对象的顺序,而不是只需要知道正确的顺序,最后将对象复制到一个新的数组中。

复制 128 字节几乎肯定比执行字节比较慢得多,即使有额外的间接性也是如此。因此,为了获得最佳性能,您需要查看的是移动,而不是比较,处理指针是避免大部分移动的一种方法。

您可以在最后执行复制时构建游程编码。

当然,使用一些自定义排序算法可能会更快,该算法在您的案例中特别使用数字(64、“大约 128”和 1)。但即使是简单的问题,如“哪个最快 - 引入排序、堆排序或合并排序”,如果不编写和运行代码,通常也无法回答。

【讨论】:

是的,我正计划使用一个字节来存储索引。我说我需要双缓冲是对的? 您并不严格需要一个:您需要根据任意排列重新排列数组,这可以通过识别排列的循环并重新排列每个循环来就地完成反过来,只使用一个对象的额外空间。另外:不能保证,但我的猜测是使用一个词来存储索引和另一个词作为排序键会更快,而不是每个字节。所以试试两者,看看你喜欢哪一个。 好的,我会做实验。谢谢【参考方案3】:

排序不会变慢,因为您将排序指针或对结构的引用,而不是内存中的实际结构。

【讨论】:

【参考方案4】:

事实上,你的键是整数,而且真的不多, 可能性是 Bucket Sort,桶大小为 1,非常适用。

【讨论】:

唯一的问题是我相信我必须为桶分配 16384 字节,并且还需要为实际数据使用双缓冲区。它是否正确?这会比堆排序快吗? 您可以通过使用指向数据的指针向量映射来添加存储桶。 我感觉向量中的所有分配都会减慢速度。 将数组声明为静态的,并将其设为整数。它会像闪电一样运行。

以上是关于使用字节比较对结构进行排序的最佳排序算法?的主要内容,如果未能解决你的问题,请参考以下文章

数据结构所有排序算法性能分析与比较

数据结构与算法之排序算法:交换排序

数据结构与算法:排序

数据结构6种内部排序算法的比较

知识分享:数据结构常用 7 种排序算法(无基数排序)

数据结构-排序算法总览