对n个第一个元素已经sorting的向量进行sorting?
考虑N
元素的std::vector
v
,并且认为n
第一个元素已经被sorting, n < N
,其中(Nn)/N
非常小:
有一个聪明的方法使用STLalgorithmsorting这个向量比完整的std::sort(std::begin(v), std::end(v))
更快吗?
编辑:澄清:(Nn)未分类的元素应插入在已sorting的n个第一个元素内的正确位置。
EDIT2:奖金问题:以及如何findn? (对应于第一个未分类的元素)
void foo( std::vector<int> & tab, int n ) { std::sort( begin(tab)+n, end(tab)); std::inplace_merge(begin(tab), begin(tab)+n, end(tab)); }
编辑2
auto it = std::adjacent_find(begin(tab), end(tab), std::greater<int>() ); if (it!=end(tab)) { it++; std::sort( it, end(tab)); std::inplace_merge(begin(tab), it, end(tab)); }
仅对其他范围进行sorting,然后使用std :: merge 。
最佳解决scheme是独立sorting尾部,然后执行就地合并,如此处所述
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.22.5750
该algorithm是相当复杂的,通常被认为是“不值得的努力”。
当然,用C ++你可以使用现成的std::inplace_merge
。 但是,该algorithm的名称是非常具有误导性的。 首先,不能保证std::inplace_merge
实际上就地工作。 而实际上,这并不能保证它不是一个完整的sorting。 在实践中,它归结为尝试它,看看它是否足够你的目的。
但是,如果你真的想把它做到位,并且比正式的更有效率,那么你将不得不手动实现它。 STL可能会提供一些实用algorithm的帮助,但是它不能提供任何“只需调用标准函数”的固定解决scheme。
在N - n
最后的元素上使用插入sorting:
template <typename IT> void mysort(IT begin, IT end) { for (IT it = std::is_sorted_until(begin, end); it != end; ++it) { IT insertPos = std::lower_bound(begin, it, *it); IT endRotate = it; std::rotate(insertPos, it, ++endRotate); } }
Timsortsortingalgorithm是由Pythonista Tim Peters开发的混合algorithm。 它在数组内的任何地方使用已sorting的子段进行最佳使用,包括开始。 虽然如果你确定知道前 n个元素已经被sorting,那么你可能会发现一个更快的algorithm,但是这个algorithm应该对所涉及的整个类别的问题有用。 维基百科将其描述为:
该algorithmfind已经sorting的数据的子集,并使用该知识来更有效地对余数进行sorting。
用蒂姆·彼得斯自己的话来说,
它在多种部分有序的arrays(小于lg(N!)比较所需的,less至N-1)上具有超自然的性能,但是与Python之前高度调整的随机arrays上的高度调整的样本杂合体一样快。
蒂姆·彼得斯(Tim Peters)在这个没有date的文本文件中描述了全部细节 这些例子是用Python编写的,但是对于不熟悉它的语法的人来说,Python应该是非常易读的。
使用std :: partition_point(或is_sorted_until)来查找n。 那么如果纳米是小插入sorting(线性search+标准::旋转)。
我假设你的问题有两个目的:
- 改进运行时(使用一种聪明的方式)
- 很less费力(限于STL)
考虑到这些目标,我强烈build议不要这个特定的优化,除非你确信这个努力是值得的。 据我所知,std :: sort()实现了快速sortingalgorithm,它在预分类input上几乎同样快,以确定input是否被sorting。
您可以尝试将数据结构更改为sorting/优先级队列,而不是干涉std :: sort。