常量迭代器的问题

时间:2017-11-16 19:20:35

标签: c++ c++11 iterator

我正在尝试编写一个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迭代器一起使用?

3 个答案:

答案 0 :(得分:2)

  

如果我传递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!
}

答案 1 :(得分:1)

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

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
  3. 你的例子产生6和37.它应该是36而不是37吗?

答案 2 :(得分:0)

解决了这个练习如下,它适用于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<Iterator>::value_type代替Iterator::value_type(不使用const iters和简单指针(如int *))