# STL源码之rotate函数结合图和实例分析

emplate <class ForwardIterator, class Distance>
// Distance类型仅仅对于random iterator的实现版本有意义，但为了便于上层代码便于调用，所以使用// 了同样的签名。
void __rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last, Distance*, forward_iterator_tag)
{
for (ForwardIterator i = middle; ;) {
// iter_swap用于交换两个iterator所指向的内容。
// 也可以这样写：swap(*first, *i);
iter_swap(first, i);
++first;
++i;
if (first == middle) {
// first和i同时到达末尾，元素交换结束，返回。
if (i == last)
return;
// first首先到达末尾，说明A的长度小于B。
middle = i;
}
// i首先到达末尾，说明A的长度大于B。
else if (i == last)
i = middle;
}
}

template <class BidirectionalIterator, class Distance>
void __rotate(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Distance*, bidirectional_iterator_tag)
{
// 翻转A
reverse(first, middle);
// 翻转B
reverse(middle, last);
// 翻转A'B'
reverse(first, last);
}

__gcd是求两个数的最大公约数，也是循环位移的遍数。

template <class RandomAccessIterator, class Distance>
void __rotate(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Distance*, random_access_iterator_tag)
{
// gcd是求最大公约数的函数。
Distance n = __gcd(last - first, middle - first);

while (n--)   //注意这里是n--，我因为没看见这个n--，时间浪费了半天
// 需要执行__rotate_cycle n次。
__rotate_cycle(first, last, first + n, middle - first, value_type(first));
}

template <class RandomAccessIterator, class Distance, class T>
void __rotate_cycle(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator initial, Distance shift, T*)
{
T value = *initial;
RandomAccessIterator ptr1 = initial;
RandomAccessIterator ptr2 = ptr1 + shift;

while (ptr2 != initial) {
*ptr1 = *ptr2;
ptr1 = ptr2;
if (last - ptr2 > shift)
ptr2 += shift;
else
ptr2 = first + (shift - (last - ptr2));
}

*ptr1 = value;
}

template <class EuclideanRingElement>
EuclideanRingElement __gcd(EuclideanRingElement m, EuclideanRingElement n)
{
while (n != 0) {
EuclideanRingElement t = m % n;
m = n;
n = t;
}

return m;
}

#include <iostream>
#include <assert.h>

int calc_gcd(int m, int n)
{
if(m < n)
std::swap(m, n);
if(n == 0)
return m;
calc_gcd(n, m%n);
}

template <typename T>
void cycle_rotate(T *arr, int *first, int *last, int *initial, int rotate_num)
{
T value = *initial;
T *ptr1 = initial, *ptr2 = ptr1 + rotate_num;
while(ptr2 != initial){
*ptr1 = *ptr2;
ptr1 = ptr2;
if(last - ptr2 >= rotate_num)  //可以等于，因为是下标
ptr2 += rotate_num;
else
ptr2 = first + (rotate_num - (last - ptr2)) - 1; //注意要减一，因为我这里用的是下标
}
*ptr1 = value;
}

template <typename T>
void rotate(T* arr, int start, int end, int rotate_num)
{
assert(start >= 0 && rotate_num > start && rotate_num <= end+1);
int gcd = calc_gcd(end-start+1, rotate_num);
while(gcd--)
cycle_rotate(arr, arr+start, arr+end, arr+start+gcd, rotate_num);
}

int main()
{
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int len = sizeof(array) / sizeof(int);
rotate(array, 0, len-1, 5);
for(auto i : array)
std::cout<<i<<' ';
std::cout<<std::endl;

return 0;
}


12-03 1065

12-08 342

04-26 149

05-03 60

12-27 113

04-26 1879

04-25 2235

10-30 4109

07-02 1767

10-29 34

#### stl::rotate 数组循环移位

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。