【问题标题】:How to make a stable sort of binary values in linear time?如何在线性时间内生成稳定的二进制值?
【发布时间】:2013-08-23 09:28:47
【问题描述】:

假设我们有一个:

class Widget;
std::vector<Widget>;

我们有一个函数:

bool belongsToLeft(Widget w);

我想根据这个谓词对容器进行排序。到目前为止,我认为这个算法。它从范围的两端进行。一旦它找到一对同时属于另一端的值,它就会交换它们。

template <typename TIterator, typename TPredicate>
TIterator separate(TIterator begin, TIterator end, TPredicate belongsLeft)
{
    while (true)
    {
        while (begin != end && belongsLeft(*begin))
            ++begin;
        while (begin != end && !belongsLeft(*end))
            --end;
        if (begin == end)
            return begin;
        std::swap(*begin, *end);
    }
}

问题是这个算法不稳定:

#include <vector>
#include <iostream>

int main()
{
    std::vector<int> numbers = {6, 5, 4, 3, 2, 1};
    separate(numbers.begin(), numbers.end(), [](int x){return x%2 == 0;});

    for (int x : numbers)
        std::cout << x << std::endl;
    return 0;
}

输出:

6
2
4
3
5
1

如何修改此算法以使其稳定并保持线性时间?

【问题讨论】:

  • 你为什么不用std::stable_sort()
  • 我想利用只有两个可能值的事实,以便算法在线性时间内运行。
  • 只有在*end &gt; *begin 不能保证的情况下才能进行交换;将谓词放在开始/结束上。
  • 您认为示例中的输出到底有什么问题?
  • @Steven 我想要一个稳定的排序。也就是说,数字应该以与输入相同的相对顺序出现:6、4、2、5、3、1

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


【解决方案1】:

使用std::stable_partition 和谓词将numbers 分成线性复杂度的两部分

#include <algorithm>

std::stable_partition(
    numbers.begin(), numbers.end(), 
    [](int x) { return x % 2 == 0; } // or belongsToLeft()
);

【讨论】:

  • 哇!谢谢!标准库总是让我惊叹!
  • 如果您知道您的手写算法需要做什么,请想一个合适的名称,然后使用词库查找类似于标准库算法的替代名称,例如thesaurus.com/browse/separate 并显示分区为条目
猜你喜欢
  • 2017-06-30
  • 2014-01-15
  • 2012-05-11
  • 2012-10-11
  • 2022-01-08
  • 2014-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多