【问题标题】:Problems with constant iterators常量迭代器的问题
【发布时间】:2017-11-16 19:20:35
【问题描述】:

我正在尝试编写一个 tempate 函数,它接受一个序列(通过 2 个迭代器)并计算该序列的排列数,其中没有连续的相同元素。 我就是这么做的

    template<class Iterator>
    size_t count_perm(Iterator p, Iterator q)
    {
        if (p == q)
            return 1;
        size_t count = 0;
        while(std::next_permutation(p, q)){
              if(std::adjacent_find(p,q) != q)
              ++count;
        }
    }
/*Example

std::array<int, 3> a1 = {1,2,3};
size_t c1 = count_perm(a1.begin(), a1.end()); // 6

std::array<int, 5> a2 = {1,2,3,4,4};
size_t c2 = count_perm(a2.begin(), a2.end()); // 36*/

如果我通过 const 迭代器,此代码将不起作用。我应该更改哪些内容才能使其与 const 迭代器一起使用?

【问题讨论】:

  • 我建议您与math.stackexchange.com 的人交谈。我敢打赌,他们可以为您提供一种更有效的计算方式。

标签: c++ c++11 iterator


【解决方案1】:

如果我通过 const 迭代器,此代码将不起作用。我应该更改哪些内容才能使其与 const 迭代器一起使用?

您不能:std::next_permutation() 修改值,因此与 const 迭代器不兼容。

-- 编辑--

OP 询问

我怎样才能以正确的方式实现这个功能?

我建议你遵循 Jarod42 的建议:在副本上工作。

我建议如下

template <class Container>
size_t count_perm (Container c)  // note: c is a copy
{
    if ( c.cbegin() == c.cend() )
        return 1;

    size_t count = 0U;

    std::sort(c.begin(), c.end());

    if (std::adjacent_find(c.cbegin(), c.cend()) != c.cend()))
     {
       std::size_t ui = c.size();

       for ( count = ui ; --ui > 1 ; count *= ui )
        ; 

       // count now is c.size() ! (factorial of)
     }
    else
     {
       while (std::next_permutation(c.begin(), c.end()))
          if (std::adjacent_find(c.cbegin(), c.cend()) != c.cend())
             ++count;
     }

    return count; // remember this return!
}

【讨论】:

  • “我应该改变什么才能使它与 const 迭代器一起工作?”:创建副本 :-)
  • @Jarod42 - 我知道;但我认为有时最好是作为分工来指出问题所在。
  • @Jarod42 谢谢大家。我怎样才能以正确的方式实现这个功能?
  • "为什么不为零?"因为只有一个结果集:空集。
  • @KillzoneKid:那又怎样? 0 个元素给你{},1 个元素给你{a},2 个元素给你{a,b},{b,a}。这些计数是 1、1 和 2。没错。
【解决方案2】:

为您修复了模板函数(仍然需要非常量迭代器):

template<class Iterator> size_t count_perm(Iterator p, Iterator q)
{
    if (p == q || std::all_of(p, q, [&](auto &el) {return el == *p; })))
        return 0;

    size_t count = 1;
    std::sort(p, q);

    while (std::next_permutation(p, q)) 
        if (std::adjacent_find(p, q) == q)
            ++count;

    return count;
}
  1. 你应该返回计数
  2. 当没有找到相邻元素时,std::adjacent_find 返回end,所以你应该== q 而不是!= q

您的示例生成 6 和 37。应该是 36 而不是 37?

【讨论】:

  • 虽然您删除了订单要求,但您并没有解决 constness OP 的范围问题。
  • @Jarod42 我知道,无论有没有 const 迭代器,该函数都无法使用。可以在函数内创建临时容器,但我不知道这是否是最好的解决方案
【解决方案3】:

如下解决了这个练习,它与 const 迭代器一起工作:

template<class Iterator>
size_t count_permutations(Iterator p, Iterator q)
{
    using T = typename std::iterator_traits<Iterator>::value_type;
    if (p == q)
        return 1;
    std::vector<T> v(p,q);
    std::sort(v.begin(), v.end());
    size_t count = 0;
    do{
        if(std::adjacent_find(v.begin(),v.end()) == v.end()) {
            ++count;
        }

    } while(std::next_permutation(v.begin(), v.end()));
    return count;
}

问题是使用 std::type_traits&lt;Iterator&gt;::value_type 而不是 Iterator::value_type(不能使用 const iters 和简单指针(如 int*))

【讨论】:

    猜你喜欢
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    相关资源
    最近更新 更多