Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用自定义非纯交换函数参数化算法?_C++_Algorithm_Lambda_Stl_Overload Resolution - Fatal编程技术网

C++ 如何使用自定义非纯交换函数参数化算法?

C++ 如何使用自定义非纯交换函数参数化算法?,c++,algorithm,lambda,stl,overload-resolution,C++,Algorithm,Lambda,Stl,Overload Resolution,我想应用Eric Niebler定制点的算法。但他的方法意味着STL的修改。无论哪种方式,即使这是他的方法不能允许我从函数范围传递有状态重载的点,我想,不是吗?您可以只在范围对象中包含值 struct Range { I first; I second; L & list; } void swap(Range & l, Range & r) { assert(std::addressof(l.list) == std::addressof(r.list));

我想应用Eric Niebler定制点的算法。但他的方法意味着STL的修改。无论哪种方式,即使这是他的方法不能允许我从函数范围传递有状态重载的点,我想,不是吗?

您可以只在范围对象中包含值

struct Range { I first; I second; L & list; }

void swap(Range & l, Range & r)
{
    assert(std::addressof(l.list) == std::addressof(r.list));
    using std::swap;

    auto ll = std::next(l.second);
    auto rr = std::next(r.second);
    if (ll == r.first) {
        l.list.splice(rr, l.list, l.first, ll);
    } else if (rr == l.first) {
        l.list.splice(ll, l.list, r.first, rr);
    } else {
        L temp;
        temp.splice(std::cend(temp), l.list, l.first, ll);
        l.list.splice(ll, l.list, r.first, rr);
        l.list.splice(rr, std::move(temp));
    }   
    swap(l.first, r.first); 
    swap(l.second, r.second); 
}

如果与基于交换函数重载的方法相比,我发现了一种更好的方法来实现所需的功能:应用更改的双通道方法。它只给出了线性开销,而不是算法的复杂度

#include <utility>
#include <algorithm>
#include <vector>
#include <list>
#include <iostream>
#include <random>
#include <cassert>

inline
std::ostream & operator << (std::ostream & out, const std::pair< int, int > & p)
{
    return out << '{' << p.first << ", " << p.second << '}';
}

int main()
{
    using L = std::list< std::pair< int, int > >;
    using I = typename L::const_iterator;
    using P = std::pair< I, I >;
    using R = std::vector< P >;
    L values;
    R ranges;
    auto l = std::cbegin(values);
    for (int i = 0; i < 10; ++i) {
        l = values.emplace(std::cend(values), i, 0);
        auto & p = ranges.emplace_back(l, l);
        for (int j = 1; j <= i; ++j) {
            p.second = values.emplace(std::cend(values), i, j);
        }
    }
    for (const auto & p : values) {
        std::cout << p << std::endl;
    }
    std::cout << "-----" << std::endl;
    std::shuffle(std::begin(ranges), std::end(ranges), std::mt19937{std::random_device{}()});
    l = std::cbegin(values);
    for (const auto & range : ranges) {
        auto r = std::next(range.second);
        if (l != range.first) {
            values.splice(l, values, range.first, r);
        }
        l = r;
    }
    assert(l == std::cend(values));
    for (const auto & p : values) {
        std::cout << p << std::endl;
    }
}

不要认为它适用于迭代器失效规则更严格的容器。

与其说范围是std::pair的容器,不如说结构{I first;I second;L&list;}的容器?另外,所有的p.seconds都是形式I,I的L的元素。您打算这样做吗?@Caleth这是一个可以考虑的解决方案,但它会导致额外的数据重复。@Caleth std::pair元素就是一个例子。第一个只是一个范围内的数字,第二个是该范围内的唯一值。这是为了便于视觉区分。所有范围的长度都不同。对于结构{I first;I second;L*list={};},还需要重载move构造函数和move赋值运算符以正确地互操作w/std::swap。您的意思是定义自由函数。我喜欢你的解决方案。
#include <utility>
#include <algorithm>
#include <vector>
#include <list>
#include <iostream>
#include <random>
#include <cassert>

inline
std::ostream & operator << (std::ostream & out, const std::pair< int, int > & p)
{
    return out << '{' << p.first << ", " << p.second << '}';
}

int main()
{
    using L = std::list< std::pair< int, int > >;
    using I = typename L::const_iterator;
    using P = std::pair< I, I >;
    using R = std::vector< P >;
    L values;
    R ranges;
    auto l = std::cbegin(values);
    for (int i = 0; i < 10; ++i) {
        l = values.emplace(std::cend(values), i, 0);
        auto & p = ranges.emplace_back(l, l);
        for (int j = 1; j <= i; ++j) {
            p.second = values.emplace(std::cend(values), i, j);
        }
    }
    for (const auto & p : values) {
        std::cout << p << std::endl;
    }
    std::cout << "-----" << std::endl;
    std::shuffle(std::begin(ranges), std::end(ranges), std::mt19937{std::random_device{}()});
    l = std::cbegin(values);
    for (const auto & range : ranges) {
        auto r = std::next(range.second);
        if (l != range.first) {
            values.splice(l, values, range.first, r);
        }
        l = r;
    }
    assert(l == std::cend(values));
    for (const auto & p : values) {
        std::cout << p << std::endl;
    }
}