是否有一个函数来交换c ++向量中的两个段?

时间:2014-10-11 19:39:30

标签: c++ algorithm c++11 vector swap

我知道有std::swap可以在向量中交换两个元素,或者迭代交换两个长度相同的段。例如,我可以编写一个循环来交换向量bcd中的efgabcdefgh,从而生成aefgbcdh。但我可以交换bcdef(不同长度)吗?或者std::vector中是否还有其他可以实现此功能的功能?

3 个答案:

答案 0 :(得分:6)

如果细分相邻,您可以使用std::rotate。例如:

std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

我想说我想将{ 1, 2, 3 }{ 4, 5, 6, 7 }交换。我可以这样做:

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

如果细分不相邻,您可以使用rotate两次来完成,但它可能会比严格必要的工作更多。例如,将{ 1, 2 }{ 4, 5, 6, 7 }

交换
std::rotate(v.begin() + 1, v.begin() + 4, v.begin() + 8);
std::rotate(v.begin() + 5, v.begin() + 7, v.begin() + 8);

答案 1 :(得分:3)

这减少到等长的间隔交换,然后是旋转。

等长间隔交换减少了“将间隔移动到另一个地点”的问题,可以使用std::rotate就地实施。

如果半开间隔[a,b)向前移动到x,则:

std::rotate( a,b,x );

如果向后移动到y那么:

std::rotate( y,a,b );

如果我们假设我们可以按正确的顺序获取间隔(序列中右边的前一个间隔),那么我们可以这样做:

template<class I>
void swap(I a, I b, I x, I y){
  using std::distance; using std::next; using std::advance;
  auto d_ab=distance(a,b);
  auto d_xy=distance(x,y)
  auto d=(std::min)(d_ab,d_xy);
  std::swap_ranges(a,next(a,d),x);
  advance(a,d);
  advance(x,d);
  if (a==b){
    std::rotate(b,x,y);
  }else{
    std::rotate(a,b,x);
  }
}

可以完成避免多次遍历元素的微优化,但对于向量迭代器,额外的进展可以接下来是免费的。

一个工业强度的人可以进行标记调度,为随机访问迭代器写一个光滑的,并且对于其他迭代器执行双迭代器循环交换元素(边界检查的手动交换范围),类似rotate at结束。

如果我们不知道订单是abxy,我们需要随机访问迭代器(并获得{{1}的访问权限}})。然后我们需要包含上面的<调用来改变参数的顺序。

通过访问std::rotate迭代器,我们仍可以使用前向迭代器进行效率低下。

答案 2 :(得分:1)

void swap(std::vector<int>& v, int start1, int end1, int start2, int end2)
{
    int size2 = end2 - start2 + 1;
    int size1 = end1 - start1 + 1;
    auto begin = v.begin() + start1;
    auto end = v.begin() + end2 + 1;

    std::rotate(begin, v.begin() + start2, end);
    std::rotate(begin + size2, begin + size2 + size1, end);
}

这是使用双旋转技巧完成工作的通用版本:)