如果我的std::vector
初始化如下:
0 1 2 3 4 5
我怎样才能最好地将4传播到第一位?即我想要std::vector
处于这种状态:
4 0 1 2 3 5
移除4并重新插入它可能很昂贵,因为前面的插入是O(N)
,我相信。我在考虑在连续的地方交换值(比如在冒泡排序中),但那也是O(N)
。是否正在使用另一个容器,例如std::list
?
编辑:
在看到一些混淆之后,让我澄清一下,我的目标是在std::vector
中另一个已知位置的值前面的std::vector
中的已知任意位置添加值。
答案 0 :(得分:15)
即使有可接受的答案,正常的C ++方式是使用提供的算法。在这种情况下,它应该是std::rotate
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator> // for std::advance
int main(int argc, char** argv) {
std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
std::cout << "Before: ";
for (auto element : v)
std::cout << element << " ";
std::cout << std::endl;
// edit starts here
auto first=v.begin();
auto nfirst=first;
std::advance(nfirst, 4); // Iterator of first element to move to front
auto last=nfirst;
std::advance(last, 1); // 1 is element count for moving to front
std::rotate(first, nfirst, last);
// edit ends here
std::cout << "After: ";
for (auto element : v)
std::cout << element << " ";
std::cout << std::endl;
return 0;
}
编辑:
在与Luc Touraille讨论后,我看到了改进的空间。现在解决方案使用std::advance
进行迭代器操作。所以它应该使用前向迭代器,这是std::rotate
的要求。
答案 1 :(得分:7)
如果O(N)出现问题,更改容器(例如std :: deque)是唯一的选择。
但是,请确保O(N)确实是个问题!
答案 2 :(得分:3)
说真的,我强烈怀疑O(n)确实是你实际代码中的一个问题。有一个更好的理由使用std::vector
而不是std::list
,比更好的内存局部性和更少的内存开销,而不仅仅是大O.但您仍然可以优化标准方法(要求dst
在src
之前),
std::vector<int>::iterator src = ..., dst = ...;
...
auto tmp = std::move(*src);
vec.erase(src);
vec.insert(dst, std::move(tmp));
将O(n)个遍历(erase
中的一个左移和insert
中的一个左移)转换为一个(可能更小)的一个:
auto tmp = std::move(*src);
for(auto iter=src; iter!=dst; --iter)
*iter = std::move(*std::prev(iter));
*dst = std::move(tmp);
编辑:请注意我上面的代码段除了在他的回答中按照 Jan 的建议不必要地复制std::rotate
之外别无其他。
答案 3 :(得分:2)
作为@JanHerrmann提供的优秀答案的补充,这是一个用于移动范围内元素的通用函数:
#include <algorithm>
#include <iostream>
#include <iterator>
// Moves the element src before dst, maintaining the order of other values
template <typename RandomAccessIt>
void moveElement(RandomAccessIt src, RandomAccessIt dst)
{
if (dst == src)
{
return;
}
if (dst < src)
{
std::rotate(dst, src, src + 1);
}
else
{
std::rotate(src, src + 1, dst);
}
}
void printVector(const std::vector<int> &v)
{
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
}
int main() {
std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
printVector(v); // 0 1 2 3 4 5
moveElement(v.begin() + 4, v.begin());
printVector(v); // 4 0 1 2 3 5
moveElement(v.begin() + 2, v.begin() + 2);
printVector(v); // 4 0 1 2 3 5
moveElement(v.begin() + 2, v.begin() + 3);
printVector(v); // 4 0 1 2 3 5
moveElement(v.begin() + 2, v.end());
printVector(v); // 4 0 2 3 5 1
}