对STL 中算法rotate Random access iterator 源码理解
2015-06-03 16:49
471 查看
主要通过下面的表中例子来理解:给出了源码(《STL源码解析》),结合代码看例子更容易理解
对random access iterator版rotate进行举例如:
对random access iterator版rotate进行举例如:
这个算法有点像希尔排序,翻转的前部分长度是向后增量(位移量L1),翻转的后部分长度是向前增量(位移量L2),也可以将数列理解为一个环,位移量就是前部分长度值。而前后长度的最大公因子对应的值就是每次循环的初始位置,ptr1和ptr2为移动游标,ptr1从初始位置开始,而ptr2和ptr1的距离为位移量L1(前部分长度)大小,如果ptr2加上位移量L1超出数列总长度,则将ptr2位置向前移向L2大小,如果在移动后ptr2回到原定则将初始保留值赋给ptr1,推出循环。 | ||
初始状态 | 1 2 3 4 5 6 7 8 9 | L1=3,L2=6,n=3,故需要循环处理3次 |
n=3 | 1 2 6 4 5 9 7 8 3 | 从第3个数开始,ptr2如果经过一系列增量回到这个初始点着跳出循环(下同) |
n=2 | 1 5 6 4 8 9 7 2 3 | |
n=1 | 4 5 6 7 8 9 1 2 3 | |
初始状态 | 1 2 3 4 5 6 7 8 9 | L1=5,L2=4,n=1 故需要循环处理1次 |
n=1 | 6 7 8 9 1 2 3 4 5 | |
初始状态 | 1 2 3 4 5 6 7 8 | L1=2,L2=6,n=2 故需要循环处理2次 |
n=2 | 1 4 3 6 5 8 7 2 | |
n=1 | 3 4 5 6 7 8 1 2 | |
// 最大公因数,利用辗转相除法 // __gcd() 应用于 __rotate() 的 random access iterator 版 template <class EuclideanRingElement> EuclideanRingElement __gcd(EuclideanRingElement m, EuclideanRingElement n) { while (n != 0) { //这里是一个迭代 EuclideanRingElement t = m % n; m = n; n = t; } return m; } // rotate 的 random access iterator 版 template <class RandomAccessIterator, class Distance> void __rotate(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Distance*, random_access_iterator_tag) { // 以下迭代器的相减操作只使用于RandomAccessIterator // 取全长和前段(移动的位数)的最大公因数 Distance n = __gcd(last - first, middle - first); // 链数为gcd(m,n) 。链中元素个数为n/gcd(m,n)。 while (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; //ptr1指向“槽”的位置 if (last - ptr2 > shift) //还没有到达最后一个元素 ptr2 += shift; else ptr2 = first + (shift - (last - ptr2)); //此处可以将这个代数式解开发现如:ptr2=ptr2-翻转第二部分的长度 这样就非常好了理解了 } *ptr1 = value; } // 分派函式(dispatch function) template <class ForwardIterator> inline void rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last) { if (first == middle || middle == last) return; //交换的中间点在首尾,返回 __rotate(first, middle, last, distance_type(first), iterator_category(first)); } //_copy版本的rotate template <class ForwardIterator, class OutputIterator> OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result) { return copy(first, middle, copy(middle, last, result)); }
相关文章推荐
- 浅析STL中的常用算法
- c++ STL容器总结之:vertor与list的应用
- C++在成员函数中使用STL的find_if函数实例
- 关于STL中list容器的一些总结
- 关于STL中的map容器的一些总结
- 浅析stl序列容器(map和set)的仿函数排序
- STL list链表的用法详细解析
- stl容器set,map,vector之erase用法与返回值详细解析
- STl中的排序算法详细解析
- 关于STL中vector容器的一些总结
- 关于STL中set容器的一些总结
- 简单说说STL的内存管理
- CppUtest发现的STL容器内存泄漏问题
- STL中算法
- STL简单应用
- vector-list-deque
- 三十分钟掌握STL
- 1.sort()
- 刚刚接触到一个STL的函数make_pair()
- 简单使用C++的STL