C ++,std :: list的左右旋转

时间:2018-08-28 07:45:23

标签: c++ algorithm list vector rotation

有什么方法可以将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 个答案:

答案 0 :(得分:5)

有关调用的唯一语法问题

 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,在这种情况下,您需要随机连接访问要求。

答案 1 :(得分:5)

您不能将其添加到std::list迭代器中,因为它不是随机访问的。但是您可以增加它。这就是std::next为您做的事情:

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

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

那是不必要的低效。如果要遍历列表中所有复杂度为O(n²)的项目。很快就会变得很慢。

相反,只需将第一项拼接在列表的末尾即可。

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

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