STL之rotate

2023-11-03

STL对左旋转字符串针对三种不同数据结构进行了不同的实现。

对单向链表采用的是同步位移,双向链表是三次翻转,都很简单,主要看看针对随机存取的数组做的循环位移实现。

STL这个版本的源码如下:

[cpp]  view plain  copy
  1. template <class RandomAccessIterator, class Distance>  
  2. void __rotate(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Distance*, random_access_iterator_tag)  
  3. {  
  4.     // gcd是求最大公约数的函数。  
  5.     Distance n = __gcd(last - first, middle - first);  
  6.   
  7.     while (n--)  
  8.         // 需要执行__rotate_cycle n次。  
  9.         __rotate_cycle(first, last, first + n, middle - first, value_type(first));  
  10. }  
  11.   
  12. template <class RandomAccessIterator, class Distance, class T>  
  13. void __rotate_cycle(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator initial, Distance shift, T*)  
  14. {  
  15.     T value = *initial;  
  16.     RandomAccessIterator ptr1 = initial;  
  17.     RandomAccessIterator ptr2 = ptr1 + shift;  
  18.   
  19.     while (ptr2 != initial) {  
  20.         *ptr1 = *ptr2;  
  21.         ptr1 = ptr2;  
  22.         if (last - ptr2 > shift)  
  23.             ptr2 += shift;  
  24.         else  
  25.             ptr2 = first + (shift - (last - ptr2));  
  26.     }  
  27.   
  28.     *ptr1 = value;  
  29. }  
  30.   
  31. template <class EuclideanRingElement>  
  32. EuclideanRingElement __gcd(EuclideanRingElement m, EuclideanRingElement n)  
  33. {  
  34.     while (n != 0) {  
  35.         EuclideanRingElement t = m % n;  
  36.         m = n;  
  37.         n = t;  
  38.     }  
  39.   
  40.     return m;  
  41. }  
__gcd是求两个数的最大公约数,也是循环位移的遍数。

举个例子来说明算法过程,数组123456789,把123翻转到右边,*first=1,*last=9,*middle=4;

要旋转字符串(123)的长度为3,字符串长度为9,3和9的最大公约数为3,因此需要翻转3遍;

第一遍从*(initial+shift)=6开始,6移到3的位置,9移到6的位置,下一个位置是ptr2 = first + (shift - (last - ptr2))=0+(3-(8-8))=3,不满足ptr2 != initial的条件,退出循环,然后*ptr1 = value,即把数字3移动到数字9的位置,从而完成了3,6,9三个数字的位移,下面的2遍循环则分别完成2,5,8和1,4,76个数字的位移,最后得到最终结果456789123。

整个算法过程可用下图表示:


自我实现C++的int版:

[cpp]  view plain  copy
  1. #include <iostream>  
  2. using namespace std;  
  3. int __gcd(int a, int b)  
  4. {  
  5.     while (b)  
  6.     {  
  7.         int tmp = a%b;  
  8.         a = b;  
  9.         b = tmp;  
  10.     }  
  11.     return a;  
  12. }  
  13. void __rotate_cycle(int *data, int first, int last, int initial, int shift)  
  14. {  
  15.     int val = data[initial];  
  16.     int pos1 = initial;  
  17.     int pos2 = initial + shift;  
  18.     while (pos2 != initial)  
  19.     {  
  20.         data[pos1] = data[pos2];  
  21.         pos1 = pos2;  
  22.         pos2 = (pos2 + shift) % (last - first + 1);  
  23.     }  
  24.     data[pos1] = val;  
  25. }  
  26. void __rotate(int *data,int first, int middle, int last)  
  27. {  
  28.     int gcd = __gcd(last - first+1, middle - first);  
  29.     cout << "循环位移" << gcd << "遍" << endl;  
  30.     while (gcd--)  
  31.     {  
  32.         __rotate_cycle(data, first, last, first + gcd, middle - first);  
  33.     }  
  34. }  
  35. void main()  
  36. {  
  37.     int data1[10] = {1,2,3,4,5,6,7,8,9,10};  
  38.     __rotate(data1, 0, 3, 9);  
  39.     for (int i = 0; i < 10; i++)  
  40.     {  
  41.         cout << data1[i] << " ";  
  42.     }  
  43.     cout << endl;  
  44.     int data2[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };  
  45.     __rotate(data2, 0, 4, 9);  
  46.     for (int i = 0; i < 10; i++)  
  47.     {  
  48.         cout << data2[i] << " ";  
  49.     }  
  50.     cout << endl;  
  51.     int data3[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };  
  52.     __rotate(data3, 0, 5, 9);  
  53.     for (int i = 0; i < 10; i++)  
  54.     {  
  55.         cout << data3[i] << " ";  
  56.     }  
  57.     cout << endl;  
  58.     int data4[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };  
  59.     __rotate(data4, 0, 6, 9);  
  60.     for (int i = 0; i < 10; i++)  
  61.     {  
  62.         cout << data4[i] << " ";  
  63.     }  
  64.     int c = 0;  
  65.     cin >> c;  
  66. }  

运行结果:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STL之rotate 的相关文章

  • Java使用图片压缩工具压缩图片的两种方法

    上代码 pom xml
  • 单元测试是什么?为什么要做单元测试?

    背锅侠 一个有个性的订阅号 1 单元测试是什么 单元测试是开发者编写的一小段代码 用于检验被测代码的一个很小的 很明确的功能是否正确 通常而言 一个单元测试是用于判断某个特定条件 或者场景 下某个特定函数的行为1 长按图片识别二维码 入群
  • [Qt 教程之Widgets模块] —— QButtonGroup抽象容器

    Qt系列教程总目录 文章目录 0 QButtonGroup简介 1 创建QButtonGroup 2 成员函数与信号 3 示例 3 1 为按钮组添加按钮 3 2 为按钮设置id 3 3 按钮组中按钮的互斥状态 3 4 获取组内所有按钮 3
  • 开源图像和视频编辑软件汇总

    1 Belender http www blender org Blender 是一套 三维绘图 及 渲染 软件 它具有跨平台的特性 支持 FreeBSD IRIX GNU Linux Microsoft Windows Mac OS X
  • django自带的序列化组件

    目录 sweetalert前端插件 django自带的序列化组件 简易分页器 带有页码的分页器 优化后的版本 模块代码 后端代码 Forms组件 校验数据 渲染标签 展示信息 widgets 注意 sweetalert前端插件 https
  • 计算机组成原理 及CPU,硬盘,内存三者的关系

    电脑之父 冯 诺伊曼 提出了组成计算机的五大部件 输入设备 输出设备 存储器 运算器和控制器 下图为 现在我们电脑的 键盘鼠标 显示器 机箱 音响等等 这里显示器为比较老的CRT显示器 现在一般都成功了液晶显示器 回想一下 在玩电脑的时候
  • chromium-cronet库的编译用于Android和ios平台实现quic协议

    chromium cronet文档 原文文档写的已经很清楚 最好还是参考官方文档 避免由于版本原因导致的问题 Cronet开发者文档 https developer android com guide topics connectivity
  • oracle学习之路(6)oracle下载地址

    ocacle下载地址 https www oracle com database technologies ocacle19c版本下载地址https www oracle com database technologies oracle d
  • flutter项目中使用

    一些小部件 GestureDetector 手势 手势表示由一个或多个指针移动组成的动作 主要有以下几种 onTap 点击事件触发 Divider 设置分割线 SharedPreferences数据存储 SharedPreferences
  • java后端分享整理

    java规范总结 1 Java 常见的代码规范 1 1 Java 自带的工具方法 1 1 1 比较两个对象是否相等 1 1 2 apache commons工具类库 1 1 2 1 字符串判空 1 1 2 3 重复拼接字符串 1 1 2 4

随机推荐

  • 图形放大效果

  • 近日总结

    P1149 火柴棒等式 题目描述 给你n根火柴棍 你可以拼出多少个形如 A B CA B CA B C 的等式 等式中的AAA BBB CCC是用火柴棍拼出的整数 若该数非零 则最高位不能是000 用火柴棍拼数字0 90 90 9的拼法如图
  • version `GLIBCXX_3.4.20‘ not found

    问题描述 编译产生如下错误 问题原因 如下图所示 usr lib x86 64 linux gnu libstdc so 6没有GLIBCXX 3 4 20 strings usr lib x86 64 linux gnu libstdc
  • 低功耗蓝牙(BLE)

    https my oschina net tingzi blog 215008 低功耗蓝牙包括的术语及概念 如上图所示 使用低功耗蓝牙可以包括多个Profile 一个Profile中有多个Service 一个Service中有多个Chara
  • CGAL+QT5配置一路踩坑总结

    总体流程参照 CGAL 5 5 Manual Using CGAL on Windows with Visual C 11条消息 通过vcpkg安装 配置 CGAL 5 2 1 Oskar Lu的博客 CSDN博客 vcpkg配置 11条消
  • ubuntu22设置静态IP 及 无线网卡启停

    标题 查看网络状态 ifconfig 开关无线网卡 sudo ifconfig wlo1 up down 搜索并显示wifi信号 sudo nmcli device wifi rescan nmcli device wifi list 连接
  • 文盘Rust -- 生命周期问题引发的 static hashmap 锁

    2021年上半年 撸了个rust cli开发的框架 基本上把交互模式 子命令提示这些cli该有的常用功能做进去了 项目地址 https github com jiashiwen interactcli rs 春节以前看到axum已经0 4
  • 路径参数和url传参

    请求参数的三种方式 第一种路径参数 后端接收 其中 PathVariabel注解的形参名字要与路径参数形参名字相等 不相等就用 value值来与路径参数名字相等 第二种url地址传参 url xxx abc get请求只能传query参数
  • 计算机白板记录,电子白板:计算机接口介绍

    电子白板 计算机接口介绍 接口类型指的是电子白板与电脑系统采用何种方式进行连接 电子白板 什么是计算机接口 目前电子白板与电脑连接常见的接口类型 有并口 也有称之为ieee1284 centronics 和串口 也有称之为rs 232接口的
  • java进阶Kafka集群实战之原理分析及优化教程全在这里

    我不去想是否能够成功 既然选择了Java 便只顾风雨兼程 我不去想能否征服Kafka集群 既然钟情于Java 就勇敢地追随千锋 我不去想Kafka集群有多么晦涩难懂 既然目标是远方 留给世界的只能是努力拼搏的背影 我不去想未来是平坦还是泥泞
  • 10.两个链表相加求和

    题目 假设链表中每一个节点的值都在 0 9 之间 那么链表整体就可以代表一个整数 给定两个这种链表 请生成代表两个整数相加值的结果链表 思路 首先是逆序相加 故这里用到了两个栈 分别存放两个链表中的值 两数相加会涉及到进位问题 所以考虑了进
  • ZeroQuant与SmoothQuant量化总结

    ref ZeroQuant Efficient and Affordable Post Training Quantization for Large Scale Transformers SmoothQuant Accurate and
  • qt程序运行时无任何错误提示信息,但是无法进入main函数

    问题 开发环境 win7 vs2013 qt 5 9 1 64位程序 qt程序运行时无任何错误提示信息 但是无法进入main函数 原因 程序中使用了visa库 使用的库的版本有问题
  • #ifndef, #define, #endif区别和使用

    文件中的 ifndef 头件的中的 ifndef 这是一个很关键的东西 比如你有两个C文件 这两个C文件都include了同一个头文件 而编译时 这两个C文件要一同编译成一个可运行文件 于是问题来了 大量的声明冲突 还是把头文件的内容都放在
  • 专访京东孙海波:大牛架构师养成记及电商供应链中区块链技术的应用

    编者按 每个人的成长曲线不同 有的人在研究生之时就已有相当知名的产品和框架 从而在接下来的工作中一路顺风顺水 有的人缺需要经历一个又一个的坑才能成长 不管是前者的聪明高效 还是后者的笨鸟先飞 他们都是在迈着脚步不断地向前 不妨 我们停下脚步
  • VS永久配置Opencv 和 Cmake配置OpenCV_contrib扩展模块 (整体思路 + 注意事项)

    1 VS永久配置Opencv 1 1 在opencv官网下载后并安装Opencv 官网地址 https opencv org 1 2 安装完成后 配置opencv的环境变量 1 3 在VS中配置opencv的属性表 步骤如下 1 在VS新建
  • 分割字符串的方法

    1 split 将一个字符串分割为子字符串 然后将结果作为字符串数组返回 2 indexOf 返回某个指定的字符串值在字符串中首次出现的位置 从左向右 没有匹配的则返回 1 否则返回首次出现位置的字符串的下标值 3 substr start
  • adb几个常见命令

    ADB Android Debug Bridge 调试桥 1 将设备连接到电脑 命令 adb connect 127 0 0 1 62001 2 检查设备连接情况 命令 adb devices 3 发送文件到设备 命令 adb push d
  • 基于Python的大数据的人才招聘数据分析与可视化平台应聘兼职-爬虫安装项目定制算法作业代做计算机毕业设计源代码

    更多项目资源 最下方联系IT实战课堂 博主拥有多年的T技术研发项目架构和教学经验 CSDN 51CTO 腾讯课堂等平台优质作者 高级讲师 培训机构联合创始人 现专注项目定制Java 小程序 前端网页 Python App NodeJs PH
  • STL之rotate

    STL对左旋转字符串针对三种不同数据结构进行了不同的实现 对单向链表采用的是同步位移 双向链表是三次翻转 都很简单 主要看看针对随机存取的数组做的循环位移实现 STL这个版本的源码如下 cpp view plain copy templat