代码之家  ›  专栏  ›  技术社区  ›  justik

C++,STD的左/右旋转::列表

  •  3
  • justik  · 技术社区  · 8 年前

    有什么方法可以使用吗 std::rotate 为了名单

    std::list<int> v = { 0,7, 1,2 };
    

    因为这些左/右旋转

    std::rotate(v.begin(), v.begin() + 1, v.end());
    std::rotate(v.rbegin(), v.rbegin() + 1, v.rend());
    

    std::vector<int> v = { 0, 7, 1, 2 };
    

    一种可能的方法是将列表复制到向量

    std::vector<int> u{ std::begin(v), std::end(v) };
    

    反之亦然,但我觉得太“冗长”。。。列表的直接旋转会导致以下错误:

    Error   C2672   'std::rotate': no matching overloaded function found    
    Error   C2676   binary '+':  std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>>' does not define this operator or a conversion to a type acceptable to the predefined operator
    

    谢谢你的帮助。

    2 回复  |  直到 8 年前
        1
  •  6
  •   lubgr    8 年前

    调用的唯一语法问题

     std::rotate(v.begin(), v.begin() + 1, v.end());
    

    是吗 std::list 迭代器不建模 random access iterators 但是 bidirectional iterators . 因此,不能对它们加上或减去整数值。相反,打电话 std::rotate 这样地

    std::rotate(v.begin(), std::next(v.begin()), v.end());
    std::rotate(v.rbegin(), std::next(v.rbegin()), v.rend());
    

    std::next 增加迭代器,不管它满足什么概念。这就是为什么有时最好首先使用它(在您的情况下,当使用 std::vector ),因为它添加了一个级别的间接寻址,而不是 someIterator + 1

        2
  •  8
  •   Cheers and hth. - Alf    8 年前

    你不能添加到 std::list 迭代器,因为它不是随机访问。但是你可以增加它。那就是 std::next 为您服务:

    void rot_slow( std::list<Item>& seq )
    {
        std::rotate( seq.begin(), next( seq.begin() ), seq.end() );
    }
    

    但是,这个逻辑,使用 std::rotate ,使用O(n)交换操作。

    那是不必要的低效。如果你想在列表中的所有项之间进行旋转,那么这就非常复杂了。它很快变得很慢。

    相反,只需在列表末尾拼接第一项:

    void rot_fast( std::list<Item>& seq )
    {
        seq.splice( seq.end(), seq, seq.begin() );
    }
    

    这使用0项交换,O(1)复杂性。