我有一个几乎正确顺序的元素列表,与正确的位置相比,元素只是相对少量的位置(例如,没有应该位于列表前面的元素是最后)。
< TL; DR>
实际来源:我有一个UDP-Packages流,包含所有标有特定时间戳的信号。评估数据表明,包没有以正确的顺序发送(或接收),因此时间戳不是经常增加而是抖动一点。要导出数据,我需要提前对其进行排序。
< / TL; DR>
我想使用std::list.sort()
对此列表进行排序。
std::list.sort()
使用的排序算法是什么?它是如何受到列表几乎排序这一事实的影响。我有一种感觉",基于分而治之的算法可能会从中获益。
对于我非常具体的问题,是否有更有效的算法?
答案 0 :(得分:1)
没有定义哪种算法使用,尽管平均应该在N log N
左右,例如快速排序。
如果您在使用数据包时将数据包附加到“队列”的末尾,那么您希望队列始终排序,那么您可以预期任何新数据包的正确位置几乎总是接近“结束”。
因此,只需将数据包插入正确的位置,而不是对整个队列进行排序。从队列的后面开始,将现有的数据包时间戳与已存在的数据包进行比较,在第一个数据包之后插入一个较小的时间戳(可能总是结束),如果没有这样的数据包,则将其插入前面。大大无序。
或者,如果你想按顺序添加所有数据包然后对它进行排序,冒泡排序应该是相当理想的,因为列表应该仍然几乎已经排序。
答案 1 :(得分:1)
如果每个元素都位于其正确位置的 k 位置,则插入排序将小于 kN 比较和交换/移动。它也很容易实现。
将此与合并排序或快速排序所需的 N * log(N)操作进行比较,以确定它是否更适合您。
答案 2 :(得分:0)
对于主要排序的数据 Insertion Sort 和 Bubble Sort 是最常见的数据。
<强> Live demo 强>
另请注意,拥有 list 结构会对索引访问产生额外的限制,因此需要索引访问的算法执行效果会更差。因此,插入排序更适合,因为它只需要顺序访问。
答案 3 :(得分:0)
对于2015年之前的Visual Studio,使用26个内部列表进行自下而上合并排序,遵循此Wiki文章中显示的算法:
https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation_using_lists
Visual Studio 2015增加了对没有默认分配器的支持。 26个内部列表初始化程序可以扩展为具有用户指定分配器的26个初始化程序实例,具体为:_Myt _Binlist[_MAXBINS+1] = { _Myt(get_allocator()), ... , _Myt(get_allocator())};
,但是Microsoft的某个人切换到基于迭代器的自顶向下合并排序。这个速度较慢,但如果比较引发异常,它的优势在于它不需要特殊恢复。该更改的作者指出了如果性能是目标,那么将列表复制到数组或向量,对数组或向量进行排序,然后从数组或向量创建新列表的速度更快。
有一个关于此的先前线索。
`std::list<>::sort()` - why the sudden switch to top-down strategy?
在你的情况下,双链表上的插入排序应该更快,如果找到一个out order节点,从列表中删除,向后扫描或转发到正确的位置并将节点插回到列表中。如果你想使用std :: list,你可以使用iterators,erase和emplace来移动&#34;移动&#34;节点,但涉及为每个移动释放和重新分配节点。用你自己的双链表实现它会更快,在这种情况下你可以操纵链接,避免在使用std :: list时释放和重新分配内存。