假设您有两个整数向量:
我想定义一个函数,允许我在两个向量之间交换一系列元素,将两个序列的起始索引和长度作为参数传递。
例如:其中和是向量,而作为参数传递的数字表示序列的起始索引和长度。
在这种情况下,我应该获得autput
v1 = 1,2, 13,14,15 ,5,6,7,8,9
v2 = 10,11,12, 3,4 ,16,17,18
我定义的示例函数的签名不是约束,如果您认为有更好的方法就可以了
答案 0 :(得分:6)
似乎所有常规STL算法都达不到您想要做的那样:
std::swap_ranges
几乎就在那里,但它需要你交换相同的长距离
std::rotate
也不错,但它要求一个范围的终点等于第二个范围的起点。
// pseudo-splice on vector
v1.insert(v1.begin() + 2 + 2, v2.begin() + 3, v2.begin() + 3 + 3);
v2.erase(v2.begin() + 3, v2.begin() + 3 + 3);
// pseudo-splice on vector
v2.insert(v2.begin() + 3, v1.begin() + 2, v1.begin() + 2 + 2);
v1.erase(v1.begin() + 2, v1.begin() + 2 + 2);
您当然可以轻松地将其抽象为一个函数模板,该模板为您的两个范围采用任意迭代器边界。
根据David的评论编辑,您可以进行一些优化以避免不必要的调整大小
// compute smallest range here, in this case it's the v1 part
std::swap_ranges(v1.begin() + 2, v1.begin() + 2 + 2, v2.begin() + 3);
// now handle the remaining part of the longest range, in this case it's element v2 + 3 + 2
std::insert(v1.begin() + 2 + 2, v2.begin() + 3 + 2);
std::erase(v2.begin() + 3 + 2);
更新:如果您使用std::list
会更容易,因为您可以使用splice
(我重新排列了insert
/ erase
部分那里模仿下面的代码)
v1.splice(v1.begin() + 2 + 2, v2, v2.begin() + 3, v2.begin() + 3 + 3);
v2.splice(v2.begin() + 3, v1, v1.begin() + 2, v1.begin() + 2 + 2);
答案 1 :(得分:1)
我认为这不会引起任何困难,除非你必须重新分配向量,如果长度为1!=长度2。
swap_elements(v1, start1, length1, v2, start2, length2){
if(length1 != length2){
//alloc mem for both of the arrays
//copy the unmodified portions of the original arrays into the new arrays
}
//swap the elements
}
答案 2 :(得分:0)
使用插入和擦除执行此操作的运行时间比下面的代码更差,因为每次调用insert和erase时,向量的其他元素必须相应地在内存中移动,并分配新的内存块,移动向量元素必要时,到新的内存块。为避免调整大小和内存问题,最好在最开始时创建两个新向量。
swap_elements(vector<int> &v1, int s1, int l1, vector<int> &v2, int s2, int l2){
vector<int> nv1(v1.begin(),v1.begin()+s1);
vector<int> nv2(v2.begin(),v2.begin()+s2);
for(int i=0;i<l2;i++)
nv1.push_back(v2[s2+i]);
for(int i=0;i<l1;i++)
nv2.push_back(v1[s1+i]);
for(int i=s1+l1+1;i<v1.size();i++)
nv1.push_back(v1[i]);
for(int i=s2+l2+1;i<v2.size();i++)
nv2.push_back(v2[i]);
v1.clear();
v2.clear();
v1=nv1;
v2=nv2;
}