C++ 是否有在c+中交换两个段的函数+;矢量?

C++ 是否有在c+中交换两个段的函数+;矢量?,c++,algorithm,c++11,vector,swap,C++,Algorithm,C++11,Vector,Swap,我知道有std::swap可以交换向量中的两个元素,或者迭代交换两个长度相同的段。例如,我可以编写一个循环来交换向量abcdefgh中的bcd和efg,从而得到aefgbcdh。但是我可以交换bcd和ef(不同的长度)吗?或者std::vector中是否有其他功能可以实现此功能?如果段相邻,则可以使用。例如: std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 如果线段不相邻,则可以使用旋转两次来执行此操作,但它可能会执行超

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

如果段相邻,则可以使用。例如:

std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
如果线段不相邻,则可以使用
旋转
两次来执行此操作,但它可能会执行超出严格必要范围的工作。例如,将
{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);

这将减少为等长间隔交换,然后进行旋转

等长间隔交换减少了“将间隔移动到另一个点”的问题,这可以通过
std::rotate
就地实现

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

std::rotate( a,b,x );
如果向后移动到
y
,则:

std::rotate( y,a,b );
如果我们假设可以按正确的顺序获得间隔(序列中左间隔先于右间隔),那么我们可以这样做:

std::rotate(v.begin() + 1, v.begin() + 4, v.begin() + 8);
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);
  }
}
模板
无效掉期(Ia、Ib、Ix、Iy){
使用std::distance;使用std::next;使用std::advance;
自动d_ab=距离(a,b);
自动d_xy=距离(x,y)
自动d=(标准::最小值)(d_ab,d_xy);
标准:交换范围(a,下一个(a,d),x);
预付款(a、d);
预付款(x,d);
如果(a==b){
标准:旋转(b,x,y);
}否则{
标准:旋转(a、b、x);
}
}
可以进行避免多次遍历元素的微优化,但对于向量迭代器来说,额外的改进几乎是免费的

一个具有工业实力的迭代器会进行标记分派,为随机访问迭代器编写一个灵活的迭代器,为其他迭代器执行双迭代器循环交换元素(手动交换范围,用于边界检查),最后使用类似的
rotate

如果我们不知道顺序是
a
b
x
y
,我们需要随机访问迭代器(并获得对
无效交换的访问权(std::vector&v,int start1,int end1,int start2,int end2)
{
int size2=end2-start2+1;
int size1=end1-start1+1;
自动开始=v.开始()+开始1;
自动结束=v.begin()+end2+1;
标准::旋转(开始,v.开始()+开始2,结束);
标准::旋转(开始+尺寸2,开始+尺寸2+尺寸1,结束);
}

这是一个使用双旋转技巧进行工作的通用版本:)

“或者std::vector中是否有其他函数可以实现此功能?”请注意,StdLib中的许多类旨在提供最少的接口。例如,
vector
没有
sort
成员函数,因为排序随机访问序列可以作为自由函数实现(不需要特权访问或实现细节)。您的段是否总是相邻的,如您的示例中的
bcd
ef
?或者您是否可能需要交换
bcd
fg
?嗯,我在那一点上停了下来(检查哪个范围先到),因为我担心迭代器类别。现在假设为RA,所以实际上可以编写一些更简单的东西(例如距离、前进)。一个模块化的解决方案可能是在一个不同的算法中首先对范围进行排序。@dyp据我所知,我需要
end
end?
@dyp和
end
我可以从
y
b
向前搜索,直到找到
A
x
end
,从而确定它们的顺序。@scx:不,那是不对的。代码按照答案中的描述工作。是的,很抱歉误导您。
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);
}