Advertisement

对STL 中算法rotate Random access iterator 源码理解

阅读量:

深入理解表中的具体实例能够帮助我们掌握相关知识。本书提供了该书中的源代码参考(如《STL源码解析》),通过查看代码进一步加深理解。

对random access iterator版rotate进行举例如:

--- --- ---
初始状态 1 2 3 4 5 6 7 8 9 L1=3,L2=6,n=3,故需要循环处理3次

| n=3 | 1 2 6 45 978
起始位置为第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次

| 初始状态
| 1 2 3 4 5 6 7 8
| L1=2,L2=6,n=2 故需要循环处理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));
    
 }

全部评论 (0)

还没有任何评论哟~