有什么方法可以将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
感谢您的帮助。
答案 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)。