对n个第一个元素已经排序的向量进行排序?

时间:2014-02-06 01:33:52

标签: c++ algorithm sorting c++11 vector

考虑std::vector vN元素,并考虑n第一个元素已经使用n < N进行排序,其中(N-n)/N非常小:

sorted/unsorted vector

是否有一种聪明的方法使用STL算法来比使用完整的std::sort(std::begin(v), std::end(v))更快地对此向量进行排序?

编辑:澄清:(N-n)未排序的元素应插入已排序的n个第一个元素中的正确位置。

EDIT2:奖金问题:以及如何找到n? (对应于第一个未排序的元素)

7 个答案:

答案 0 :(得分:23)

仅对其他范围排序,然后使用std::merge

答案 1 :(得分:20)

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));
}

答案 2 :(得分:8)

最佳解决方案是独立地对尾部进行排序,然后执行就地合并,如此处所述

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.22.5750

该算法非常复杂,通常被认为“不值得努力”。

当然,使用C ++,您可以使用现成的std::inplace_merge。但是,该算法的名称极具误导性。首先,不能保证std::inplace_merge实际上就地工作。当它实际就位时,并不能保证它不会被实现为完整的排序。在实践中,它归结为尝试它,看它是否足以满足您的目的。

但是如果你真的想要就地制作并且正式比完全排序更有效,那么你将不得不手动实现它。 STL可能有助于一些实用程序算法,但它没有提供任何“只需几次调用标准函数”的可靠解决方案。

答案 3 :(得分:4)

N - n个最后元素上使用插入排序:

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);
    }
}

答案 4 :(得分:3)

Timsort排序算法是由Pythonista Tim Peters开发的混合算法。它可以最佳地利用数组内部已经排序的子区域 ,包括在开头。虽然您可以找到更快的算法,但如果您确定特别是第一个 n元素已经排序,则此算法应该对所涉及的整体类问题有用。维基百科将其描述为:

  

该算法查找已经排序的数据的子集,并使用该知识更有效地对其余部分进行排序。

用蒂姆彼得斯自己的话说,

  

它有很多超自然的表现   各种部分有序的数组(需要少于lg(N!)的比较,和   只有N-1),但速度与Python之前高度调整的样本一样快   混合随机阵列。

详细说明in this undated text document by Tim Peters。示例是在Python中,但即使对于不熟悉其语法的人来说,Python也应该是可读的。

答案 5 :(得分:1)

使用std :: partition_point(或is_sorted_until)查找n。然后,如果n-m很小,则进行插入排序(线性搜索+ std :: rotate)。

答案 6 :(得分:1)

我认为你的问题有两个目的:

  • 改善运行时间(使用巧妙的方式)
  • 付出很少的努力(限制为STL)

考虑到这些目标,我强烈建议不要进行这种特定的优化,除非您确定这项工作是值得的。 据我所知,std :: sort()实现了快速排序算法,它几乎与预分类输入一样快,以确定输入是否/如何排序。

您可以尝试将数据结构更改为已排序/优先排序的队列,而不是插入std :: sort。