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

《STL源码剖析》学习--6章--_rotate算法分析 最近在看侯捷的《STL源码剖析》,其中有许多不太明白之处,后经分析或查找资料有了些理解,现记录一下。 《STL源码剖析》学习--6章--random access iterator _rotate算法分析 针对forward iterator 和 bidirectional iterator的_rotate 比较好理解,但是对random access iterator _rota 阅读详情

主要通过下面的表中例子来理解:给出了源码(《STL源码解析》),结合代码看例子更容易理解

对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));
}









从零开始:IBM V3700控制器更换与机器代码升级全流程指南 本文详细介绍了IBM V3700存储系统控制器更换与机器代码升级的全流程指南。从前期准备、硬件更换到版本同步,逐步解析如何应对503错误等常见问题,确保系统稳定运行。通过实战案例和优化建议,帮助工程师高效完成维护任务,提升存储系统可用性。 阅读详情

相关推荐

VS2022下OSG+OSGEARTH开发环境一键配置指南(Win10 x64+CMake自动化构建)

本文详细介绍了在VS2022环境下配置OSG和OSGEARTH开发环境的完整指南,包括软件下载、CMake自动化构建、编译实战及环境验证。通过一键配置脚本和常见问题解决方案,帮助开发者快速搭建3D开发环境,提升开发效率。

weixin_28828243的博客 405

C++高频知识总结 p1

面试总结C++C++是怎么实现接口的?C++11新特性STL容器有哪些vector、list、set、dqueue的区别iterator类型有哪些? C++ C++是怎么实现接口的? C++中,通过类实现面向对象的编程,而在基类中只给出纯虚函数的声明,然后在派生类中实现纯虚函数的具体定义的方式实现接口,不同派生类实现接口的方式也不尽相同,从而实现多态。 纯虚函数定义接口,派生类实现接口: // 基类 class Shape { public: // 提供接口框架的纯虚函数 virtual in

一只精品西红柿的进化过程 535

DRAM知识整理系列(三):部分时序参数整理

一、tCL-tRCD-tRP-tRAS(第一时序) 内存是根据行和列寻址的,当请求触发后,最初是tRAS(Active to precharge Delay),预充电后,内存才真正开始初始化RAS(Row Address Strobe)。一旦tRAS激活后,RAS开始进行需要数据的寻址。首先是行地址,然后初始化tRCD(RAS to CAS Delay),周期结束,接着通过CAS(Column Address Strobe)访问所需数据的十六进制地址。其中,从CAS开始到CAS结束,就是CAS延迟(即t

不吃鱼的猫的博客 7万+

Random Access Iterator

Random Access Iterator 树型概率DP dp[u]代表以当前点作为根得到正确结果的概率 将深度最深的几个点dp[u]很明显是1 然后很简单的转移 有k次,但我们要先看一次的情况,然后再推到k次,k次中只要有一次就可以正确,所以求出k次全失败的概率,用1去减即可 #include <bits/stdc++.h> #define ll long long u...

weixin_30817749的博客 507

Labview执行adbshell操作

一、目录 1、实现思路 2、adbshell工具配置 3、Labview执行命令窗口 1、实现思路 使用Labview的优点: 1、可以配合电源系统或者调用其他接口工具实现更高程度的自动化测试; 2、直接执行Linux相关命令,编写相关执行顺序或者逻辑更简易; --------可以用adbpush命令将.sh的脚本文件推入控制器内部执行; 3、Ubuntu系统比较大,如果只是日常执行脚本测试还是比较占用磁盘空间; 2、adbshell工具配置 1)下载adbshell工具; adbshell工具下载链

zataji的博客 2053

保姆级教程:在Ubuntu 20.04上搞定PX4飞控与T265的视觉定位(附避坑指南)

本文提供在Ubuntu 20.04上配置PX4飞控与T265视觉定位系统的详细教程,涵盖驱动安装、ROS与MAVROS桥接、PX4参数调优及故障排查。通过实测验证的步骤和避坑指南,帮助开发者实现厘米级精度的视觉定位,特别适合室内无人机应用。

weixin_29038155的博客 248

C++STL迭代器(iterator)

尽管不同容器对应不同类型的迭代器,但这些迭代器有着较为统一的定义方式,具体分为4种。迭代器的4种定义方式迭代器定义方式具体格式正向迭代器容器类名 :: iterator 迭代器名;常量正向迭代器容器类名 :: const_iterator 迭代器名;反向迭代器容器类名 :: reverse_iterator 迭代器名;常量反向迭代器容器类名 :: const_reverse_iterator 迭代器名;通过定义以上几种迭代器,就可以读取它指向的元素,*(迭代器名)

m0_62812354的博客 1127

从零到一:Silvaco中跨导曲线的自动化脚本实现

本文详细介绍了如何使用Python脚本在Silvaco中实现跨导曲线(gm曲线)的自动化分析,包括数据加载、跨导计算和结果可视化。通过自动化处理Id-Vg曲线,显著提升半导体器件工程师的工作效率,特别适用于工艺优化和DOE分析。文章还提供了批量处理和关键参数提取的高级技巧,帮助工程师快速掌握Silvaco脚本开发。

nn3456的博客 567

C++ 迭代器,常用五种迭代器

C++ 迭代器,常用五种迭代器

ken2232的博客 1409

1小时读完100篇文献的正确打开方式

各位同仁好,我是七哥。一个在高校里从事人工智能 相关领域研究,钻研用大模型AI实操的学术人。可以和七哥交流学术写作或Gemini、GPT、Claude 等大模型 学术实操相关问题,多多交流,相互成就,共同进步。文献阅读与整理一般都是最先开始、却也最容易被低估的一步。很多学术同仁一开始就陷入越读越多、越读越乱的状态:论文下载了一大堆,但真正能用来支撑自己观点的内容却始终难以提炼出来。一方面,我们需要通过文献了解该研究领域的整体发展脉络,把握当前学界已经讨论到什么程度;

智能AI让学术科研更容易 49

第11节:GPU 线程层级:线程、线程块、网格

层级标识变量功能线程threadIdx执行单元,处理数据线程块blockIdx管理多个线程,提供共享内存网格管理多个 blockGPU 编程中,合理安排线程层级,是提升性能的关键。

yumeiguo的博客 211

J. Random Access Iterator

题解:想如果到达某个点往下走能走到一次的错误概率,只要有一次对就是对的,所以求出全部错的概率,所以这个点往下走的正确概率为1-全部错误概率。结果就是根节点往下走正确的概率。 代码: #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const int ma...

Fighting 350

华为od统一考试B卷【宜居星球改造计划】Java&Go 实现

XXX年,人类通过对火星的大气进行宜居改造分析,使得火星已在理论上具备人类宜居的条件,由于技术原因,无法一次性将火星大气全部改造,只能通过局部处理形式,假设将火星待改造的区域为row * column的网格每个网格有3个值,宜居区、可改造区、死亡区,使用YES、NO、NA代替,YES表示该网格已经完成大气改造,NO表示该网格未进行改造,后期可进行改造,NA表示死亡区,不作为判断是否改造完成的宜居,无法穿过 初始化下,该区域可能存在多个宜居区,并且每个宜居区能同时在每个太阳日单位向上下左右四个方向的相邻格子进

MISAYAONE的博客 1万+

STL源码—— rotate算法理解

rotate算法实现了区间内元素的循环移位,将[first, middle)内的元素和[middle, last)内的元素互换,middle所指的元素会成为容器的第一个元素。如下图所示: 由于不同迭代器造成算法的效率有所不同,因此设计为双层架构。 template inline void rotate(ForwardIterator first, ForwardIterator m

ww32cc的博客 1233

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C++ SGI STL 的 std::rotate() 分析

在看侯捷大佬的《STL源码剖析》的过程中,关于 SGI STL 中关于标准库算法 `rotate(first, middle, last)` 的实现,记录一下自己的理解

airhaohan 的博客 520

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

《STL源码分析》 rotate函数的random access iterator版 分析上篇

《STL源码分析》 rotate函数的random access iterator版 分析 函数描述 《STL源码分析》那本书里介绍的rotate函数的作用是交换[first, middle)和[middle, last)内的元素,比如序列{1, 2, 3, 4, 5, 6, 7, 8, 9}在元素4那做旋转操作,序列就变为了{4, 5, 6, 7, 8, 9, 1, 2, 3},本质就是交换两个...

kayle1995的博客 600

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

巧用RandomAccess接口,集合遍历性能提升几十倍

文章目录前言方案验证RandomAccess 接口总结 前言 假设让你定义一个方法,供他人调用,它的功能是遍历传入的集合,你会怎么实现?方法定义如下: private void traverse(List<Integer> list) { } 方案一,使用for循环下标定位获取集合元素? private void traverse(List<Integer> list) { for (int i = 0; i < list.size(); i++) {

陈皮的JavaLib 864

STL学习笔记6 ——浅谈迭代器

文章目录一、迭代器二、迭代器的使用三、迭代器辅助函数 一、迭代器 常用的迭代器按功能强弱分为输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器 5 种。 前向迭代器(forward iterator) 假设 p 是一个前向迭代器,则 p 支持 ++p,p++,*p 操作,还可以被复制或赋值,可以用 == 和 != 运算符进行比较。此外,两个正向迭代器可以互相赋值。 支持前向迭代器的容器有:forward_list / unordered_map / unordered_multimap / u

我有两颗糖 807

【C++】STL 几种Iterators的详细介绍

前言:关于迭代器, 总共有五种:All random-access iterators are also valid bidirectional iterators.几种迭代器的关系如下: 通过这个迭代器, 我们可以随机的存取容器中的元素。 所以, 如果我将迭代器加5, 那么我们的迭代器就向前移动5个元素(如下)等等。支持++ 、–、+ n 及-n 如:向量(vector),string, 双向队列(deque), 数组(array)等容器类过这个迭代器, 我们可以对该迭代器自增(++, 对应向后移动一个

weixin_42976474的博客 473

STL入门

STL入门知识

CarryStar的博客 1116

左旋转字符串(数组循环移位)

题目描述: 定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。 如把字符串abcdef左旋转2位得到字符串cdefab。 请实现字符串左旋转的函数,要求对长度为n的字符串操作的时间复杂度为O(n),空间复杂度为O(1)。  编程之美上有这样一个类似的问题,咱们先来看一下: 设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为O(N), 且只允许使用

wolenski的专栏 2322

gcd

  gcd就是最大公约数,学递归的时候已经敲过这个代码了。但是孰不知在<algo.h>的文件库里有自带gcd函数,只需一行便能实现两个数的最大公约数了。   函数原型: template<typename _EuclideanRingElement> _EuclideanRingElement __gcd(_EuclideanRingE...

dianminba7855的博客 201

C++进阶之随机访问迭代器std::random_access_iterator:用法实例(三百八十三)

本篇目的:C++进阶之 随机访问迭代器std::random_access_iterator:用法实例基本概念是 C++ 标准库中迭代器分类中功能最强的一类,称为随机访问迭代器。它不仅支持常规的递增与递减操作,还可以进行距离跳跃、比较、加减运算和下标访问,使得迭代器行为接近指针。特性与接口随机访问迭代器支持所有前向与双向迭代器的操作,包括++--==!,此外还支持运算、[]运算符访问、<=>=比较以及两迭代器之间的距离计算,接口非常丰富。与其他迭代器的对比。

Android系统攻城狮 2069

p363:rotate的random access iterator版本是怎么一回事?

1.rotate操作实际上可以看作是左移操作。比如要求将一个序列的前m个元素和后面的元素交换位置,其实相当于将所有元素左移m位,如果移到了头,就自动跳到尾部接着移。 2.于是有这样一种算法,先让第iii位元素等于第i+mi+mi+m位,然后让第i+mi+mi+m位元素等于第i+2∗mi+2*mi+2∗m位元素。当然这里要使用模操作来应对数组越界。这样就相当于元素左移m位了。 3.但是这样有一个问题,比如对于[a, b, c, d, e, f],要求将所有元素左移两位。我们从i=0i=0i=0开始,然后iii

sinat_41619762的博客 205

我的算法不可能这么简单—最大公约数和最小公倍数

文章目录两个数的最大公约数 GCD1.辗转相除法2.内置函数两个数的最小公倍数 LCM多个数的最大公约数多个数的最小公倍数 两个数的最大公约数 GCD 整数 a 和 b 的最大公约数记为 gcd a , b) 1.辗转相除法 递归版 int GCD(int a,int b) { return b == 0 ? a : GCD(b , a % b); } 短小精悍 非递归版 int GCD(int a,int b) { while(b != 0) { int

终曲 1万+

【c++STL——第十一讲】iterator系列 (常用知识点总结)

ฅ(๑˙o˙๑)ฅ 大家好, 欢迎大家光临我的博客:面向阿尼亚学习 算法学习笔记系列持续更新中~ 文章目录一、前言二、bit set的定义三、bit set的基本运算四、bit set的常用函数五、bit set的作用最后 一、前言 在 C++ 中,严格来说,bitset并不属于stl容器的范畴,它也不支持指示器的操作。bitset提供了对数据的位操作。 bit set 压位 即如其名,bit set储存的是二进制。 它是一种类似数组的结构,它的每一个元素只能是0或1,每个元素仅用1bit.

m0_63233163的博客 3643
上一篇: Sunday算法
fiempty
博客等级 码龄15年 3粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值