c++ STL环移算法:rotate()、rotate_copy()详解_STL库

主要函数有:

  • rotate():循环移动元素。
  • rotate_copy():复制序列时循环移动元素。

为了理解如何实现环移功能,可以将序列中的元素想象成手镯上的珠子。rotate() 操作会导致一个新元素成为开始迭代器所指向的第一个元素。在旋转之后,最后一个元素会在新的第一个元素之前。

c++ STL环移算法:rotate()、rotate_copy()详解_STL库_02

rotate函数模板的行为等效于:

template <class ForwardIterator>
  void rotate (ForwardIterator first, ForwardIterator middle,
               ForwardIterator last)
{
  ForwardIterator next = middle;
  while (first!=next)
  {
    swap (*first++,*next++);
    if (next==last) next=middle;
    else if (first==middle) middle=next;
  }
}

第一个参数是这个序列的开始迭代器;第二个参数是指向新的第一个元素的迭代器,它必定在序列之内。第三个参数是这个序列的结束迭代器。

例子:

已知序列1,2,3,4,5,6,7,8。要求每间隔1s循环显示一次,当按下任意键时,退出演示。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <conio.h>
#include <time.h>
using namespace std;
void delay() {   //实现1s延时程序
    int start = time(NULL);
    int end = start;
    do {
        if (start != end)    //当start != end时时间流走的1s
            break;
    } while (end = time(NULL));
}
int main() {
    int a[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
    vector<int> v(a, a + 8);
    while (!_kbhit()) {
        copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
        rotate(v.begin(), v.begin() + 1, v.end());
        delay();
        cout << endl;
    }
    return 0;
}

c++ STL环移算法:rotate()、rotate_copy()详解_算法_03

首先conio.h不是C标准库中的头文件,是vc下的一个头文件。结合rotate函数模板的原型,利用rotate函数很好地实现了循环显示, middle位置选为v.begin()+1。当第1次执行rotate时, middle指向元素⒉,所以结果是2,3,4,5,6,7,8,1;当第2次执行rotate时, middle指向3,所以结果是3,4,5,6,7,8,1,2。以下分析,以此类推。

延时程序delay应用了系统time函数,算法是:先获取当前时间秒数start,接着在while循环中不断读结束秒数end,当 start!= end时一定是过了1s。

按任意键退出用kbhit函数,用getch函数是不行的。因为_getch()函数的返回值是获取到的字符值。需要注意的是,_getch()函数是一个阻塞函数,直到有字符输入时才会返回,所以该函数不会返回错误值。

rotate_copy函数模板的行为等效于:

template <class ForwardIterator, class OutputIterator>
  OutputIterator rotate_copy (ForwardIterator first, ForwardIterator middle,
                              ForwardIterator last, OutputIterator result)
{
  result=std::copy (middle,last,result);
  return std::copy (first,middle,result);
}

rotate_copy() 的前 3 个参数和 copy() 是相同的;第 4 个参数是一个输出迭代器,它指向目的序列的第一个元素。这个算法会返回一个目的序列的输出迭代器,它指向最后一个被复制元素的下一个位置。该函数功能是:一方面把*[middle,last)间元素依次存储到*[x,x+(last-middle))中,另一方面把*[first,middle)间元素依次存储到*[x+(last-middle),x+(last-first))中。

例子:

#include <iostream>
#include <list>
#include <algorithm>
#include <iterator>
using namespace std;
int main(){
    int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
    cout<< "原始数据a[] = ";
    copy(a, a + 8, ostream_iterator<int>(cout, " "));
    cout<< endl;
    
    list<int> v1(a, a + 8);
    list<int>::iterator middle = v1.begin();
    advance(middle, 3); //前移3位
    rotate(v1.begin(), middle, v1.end());
    cout<< "以4为中心环移(roate) : ";
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
    cout<< endl;
    
    list<int> v2(a, a + 8);
    list<int> v3;
    middle = v2.begin();
    cout<< "以4为中心环移v2-->v3(reverse_copy) : ";
    advance(middle, 3);
    rotate_copy(v2.begin(), middle, v2.end(), back_inserter(v3));
    copy(v3.begin(), v3.end(), ostream_iterator<int>(cout, " "));
    return 0;
}

c++ STL环移算法:rotate()、rotate_copy()详解_算法_04

由于是 list容器,它的内部迭代器是双向迭代器,元素4的迭代器位置不能用middle= v2.begin()+3表示,只有随机迭代器如vector中的迭代器才能执行operate+(n)操作,但是可以用系统函数advance轻松实现。