C++拾取——使用stl标准库生成等差、等比数列的方法
代码是思想的表达。阅读代码是一个猜测、求证的过程。这个过程非常费脑,所以人们都不喜欢啰啰嗦嗦的表达方式。于是在相同认知水平下,简洁高效的表达是喜闻乐见的。本文将抛砖引玉,通过一些案例讲解如何去简化代码。(转载请指明出于breaksoftware的csdn博客)
关系数列
等差数列
比如我们要构建的序列存储的值是0,1,2,3,4……9999。
常规写法
使用for循环
std::vector<int> vec;
for (int i = 0; i < 10000; i++) {vec.push_back(i);
}
简洁写法
iota
使用std标准库的iota。
std::vector<int> vec(10);
std::iota(vec.begin(), vec.end(), 0);
generate
使用std标准库的generate
std::vector<int> vec(10);std::generate(vec.begin(), vec.end(), [] {static int i = 0; return i++;});
或者
std::vector<int> vec(10);std::generate(vec.begin(), vec.end(), [n = 0]() mutable {return n++;});
partial_sum
使用std标准库的partial_sum,代码量减少了一半。 partial是局部、区间的意思,sum是累加的意思。第1、2个参数是需要被计算的容器起止迭代器,第3个参数是计算结果保存的起始迭代器。它还有第4个参数,用于描述怎么计算的。
std::vector<int> vec(10000, 1);
vec[0] = 0;
std::partial_sum(vec.begin(), vec.end(), vec.begin());
std::partial_sum方法对区间数据进行累加。具体的计算规则是
template< class InputIt, class OutputIt >
OutputIt partial_sum( InputIt first, InputIt last, OutputIt d_first );
// *(d_first) = *first;
// *(d_first+1) = *first + *(first+1);
// *(d_first+2) = *first + *(first+1) + *(first+2);
// *(d_first+3) = *first + *(first+1) + *(first+2) + *(first+3);
// ...
上述方法有个缺点,就是需要填充10000个1之后再计算。我们可以稍微修改如下,效率会好些。
std::vector<int> vec(10000);
vec[0] = 0;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), [](const int&a, int b) {return a + 1;});
如果要生成9999,9998……0这样递减的数列,则可以把第一个元素赋值为9999后,传递一个减法lambda表达式
std::vector<int> vec(10000);
vec[0] = 9999;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), [](const int& a, int b) {return a - 1;} );
等比数列
比如我们要生成1,2,4,8,16……这样2倍关系的数列。
常规写法
std::vector<int> vec;
for (int i = 0; i < 10; i++) {vec.push_back(pow(2, i));
}
精简写法
generate
std::vector<int> vec(10);std::generate(vec.begin(), vec.end(), [] {static int i = 0; return pow(2, i++);});
或者
std::vector<int> vec(10);std::generate(vec.begin(), vec.end(), [n = 0]() mutable {return pow(2, n++);});
partial_sum
std::vector<int> vec(10, 2);
vec[0] = 1;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), std::multiplies<int>());
使用比值2初始化vector容器,然后给partial_sum传递乘法函数对象。
或者使用lambda表达式
std::vector<int> vec(10);
vec[0] = 1;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), [](const int& x, int y) {return x * 2;});
如果要生成512,256……2,1这样的等比数列,则可以把容器的第一个元素设置为1024,然后给partial_sum传递除法函数对象。
std::vector<int> vec(10, 2);
vec[0] = 512;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), std::divides<int>());
或者使用lambda表达式
std::vector<int> vec(10);
vec[0] = 512;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), [](const int& x, int y) {return x / 2;});
斐波那契数列
常规写法
std::vector<int> vec(10);
vec[0] = 1;
for (auto it = std::next(vec.begin()); it != vec.end(); it++) {auto it_prev = std::prev(it);if (vec.begin() != it_prev) {*it = *it_prev + *std::prev(it_prev);}else {*it = *it_prev;}
}
精简写法
std::vector<int> vec(10);
vec[0] = 1;
std::adjacent_difference(vec.begin(), std::prev(vec.end()), std::next(vec.begin()), std::plus<int>());
adjacent_difference用于计算前后两个数据的差。第4个参数的默认操作是减法,其计算规则如下
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
ForwardIt2 adjacent_difference( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first );
// *(d_first) = *first;
// *(d_first+1) = *(first+1) - *(first);
// *(d_first+2) = *(first+2) - *(first+1);
// *(d_first+3) = *(first+3) - *(first+2);
// ...
累计型操作
比较常见的累计型操作如累加、累乘
累加
常规写法
std::vector<int> vec = { 16, 8, 4 };
int sum = 0;
for (int n : vec) {sum += n;
}
精简写法
std::vector<int> vec = { 16, 8, 4 };
int sum = std::accumulate(vec.begin(), vec.end(), 0);
代码也减少一半。
accumulate第1、2个参数是需要计算的容器的起止迭代器,第3个参数是初始计算的值。它还有第4个参数,用于描述如何累计。默认是累加操作。
我们再看个累乘操作。
std::vector<int> vec = { 16, 8, 4 };
int product = std::accumulate(vec.begin(), vec.end(), 1, std::multiplies<int>());
组合成一个字符串
常规写法
std::vector<int> vec = { 16, 8, 4 };
std::string str;
for (int n : vec) {if (!str.empty()) {str.append(",");}str.append(std::to_string(n));
}
精简写法
std::string s = std::accumulate(std::next(vec.begin()), vec.end(),std::to_string(vec[0]), // start with first element[](std::string a, int b) { return a + ',' + std::to_string(b);}
);
序列比较
两个序列中,相同偏移的元素值相等的个数
常规写法
std::vector<int> a = { 1, 2, 3, 4, 5 };
std::vector<int> b = { 5, 4, 3, 2, 1 };
int num = 0;
auto it_a = a.begin();
auto it_b = b.begin();
for (; it_a != a.end() && it_b != b.end(); it_a++, it_b++) {if (*it_a == *it_b) {num++;}
}
精简写法
std::vector<int> a = { 1, 2, 3, 4, 5 };
std::vector<int> b = { 5, 4, 3, 2, 1 };
int num = std::inner_product(a.begin(), a.end(), b.begin(), 0, std::plus<>(), std::equal_to<>());
inner_product方法对两个序列中相同位置的元素使用第5个参数指向的函数对象计算,计算的结果通过第4个参数指向的函数对象进行再计算。即
template<class InputIt1, class InputIt2, class T,class BinaryOperation1, class BinaryOperation2>
T inner_product( InputIt1 first1, InputIt1 last1,InputIt2 first2, T init,BinaryOperation1 op1,BinaryOperation2 op2 );
// 以初值 init 初始化积累器 acc ,然后
// 以表达式 acc = op1(acc, op2(*first1, *first2)) 修改它,再以表达式acc = op1(acc, op2(*(first1+1), *(first2+1))) 修改它,以此类推
两个序列元素是否完全一致(顺序无关)
比如一个序列a是1,2,3;序列b是2,1,3;序列c是1,2,1。则a和b中元素完全一致,只是顺序不一致;而c和a、b中元素不一致。可以想象这个算法不是简简单单就能写出来的。我们直接看精简写法
精简写法
std::vector<int> v1{ 1,1,2,2,5 };
std::vector<int> v2{ 5,1,2,1,2 };
bool permutation = std::is_permutation(v1.begin(), v1.end(), v2.begin(), v2.end());
is_permutation用于判断两个序列是否是同一个序列的不同(或相同)顺序排列。
相关文章:

利用NetBIOS名称与其他计算机通信
当某台计算机与网络中的其他计算机通信时,它是如何依据对方的计算机名称来得知其IP地址呢?名称解析的方法有以下几种: 检查NetBIOS名称缓存(NetBIOS name cache)广播直接向WINS服务器查询何谓NetBIOS名称:如…
编程语言性能实测,Go比Python更胜一筹?
作者 | Pawel Dziubałka, Sebastian Karasiewicz译者 | 泓技出品 | AI科技大本营(ID:rgznai100)互联网上有非常多的精彩代码,它们成了构建各种基础设施的基础。你正在阅读的这个平台同样也在致力于创建出色的代码。尽管普通用户一般不会注意…

mysql备份策略的制定
需要考虑的因素: 1. 数据库是不是都是innoDB引擎表 -》决定备份方式,热备或冷备 2. 数据量大小 -》逻辑备(量小)或物理备,全量或增量 3. 数据库本地空间是否充足 -》备份到本地或远程 4. 需要多快恢复 -》备份频率 小时…

C++拾取——使用stl标准库实现排序算法及评测
今天看了一篇文章,讲各种语言的优势和劣势。其中一个观点:haskell非常适合写算法,因为使用者不用去关心具体的计算机实现,而只要关注于操作语义。这让它在专心研究算法的人中非常受欢迎。所以很多时候,语言的争论没有太…
几行代码构建全功能的对象检测模型,他是如何做到的?
作者 | Alan Bi 译者 | 武明利,责编 | Carol 出品 | AI科技大本营(ID:rgznai100) 如今,机器学习和计算机视觉已成为一种热潮。我们都看过关于自动驾驶汽车和面部识别的新闻,可能会想象建立自己的计算机视觉模型有多酷。…

SQL操作全集
SQL操作全集 下列语句部分是Mssql语句,不可以在access中使用。 SQL分类: DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE) DML—数据操纵语言(SELECT,DELETE,UPDATE,INSERT) DCL—数据…

css3媒体查询实现网站响应式布局
响应式建筑设计、响应式家具设计、响应式办公设计,这些词可能是已有的专业名词,也可能是我自己想出来的一些名词。因为在生活中,我们常常会见到很多让人惊叹的设计,为什么同一套东西经过不同的方式变化之后会给人不同的使用感受和…
流行于机器学习竞赛的Boosting,这篇文章讲的非常全了
作者 | AISHWARYA SINGH译者 | 武明利,责编 | Carol出品 | AI科技大本营(ID:rgznai100)你能说出至少两种机器学习中的 Boosting 吗?Boosting 已经存在了很多年,然而直到最近它们才成为机器学习社区的主流。那么&#x…
并行计算——OpenMP加速矩阵相乘
OpenMP是一套基于共享内存方式的多线程并发编程库。第一次接触它大概在半年前,也就是研究cuda编程的那段时间。OpenMP产生的线程运行于CPU上,这和cuda不同。由于GPU的cuda核心非常多,可以进行大量的并行计算,所以我们更多的谈论的…

JavaScript继承详解(四)
文章截图 - 更好的排版 在本章中,我们将分析Douglas Crockford关于JavaScript继承的一个实现 - Classical Inheritance in JavaScript。 Crockford是JavaScript开发社区最知名的权威,是JSON、JSLint、JSMin和ADSafe之父,是《JavaScript: The …

C语言:在屏幕上输出信息
#include<stdio.h>int main(){printf ("This is a C program.\n");printf("welcome to bit\n");return 0;}结果:This is a C program.welcome to bitPress any key to continue转载于:https://blog.51cto.com/yaoyaolx/1715542

Colly源码解析——框架
Colly是一个使用golang实现的数据抓取框架,我们可以使用它快速搭建类似网络爬虫这样的应用。本文我们将剖析其源码,以探析其中奥秘。(转载请指明出于breaksoftware的csdn博客) Collector是Colly的核心结构体,其中包含了…

未经任何测试的源代码开放
未经任何测试的源代码开放 http://files.cnblogs.com/TextEditor/TextBoxEx.rar 这个代码只是一个Demo. 请将一个Vb.net的代码放在C盘下面,并且改名为Test.txt,然后使用菜单的Open来打开文件。 有任何问题,请在这里留言。 C#的上色还没有完成…

助力企业抗疫,360金融推出免费AI语音机器人
复工潮来临之际,为帮助各大企业进行高效的内部防疫宣传、员工行程信息收集以及快速生成公司内部防疫排班表,360金融针对复工企业的需求痛点推出了AI语音机器人,以助力企业更高效的防疫、抗疫。 针对复工企业的需求痛点,360金融人…

实现strncat
函数原型char *strncat(char *front,char *back,size_t count)参数说明back为源字符串,front为目的字符串,count为指定的back中的前count个字符。 所在库名#include <string.h>函数功能把back所指字符串的前count个字符添加到front结尾处&a…

Colly源码解析——结合例子分析底层实现
通过《Colly源码解析——框架》分析,我们可以知道Colly执行的主要流程。本文将结合http://go-colly.org上的例子分析一些高级设置的底层实现。(转载请指明出于breaksoftware的csdn博客) 递归深度 以下例子截取于Basic c : colly.NewCollecto…

无限路由 DI-624+A 详细介绍
无线路由器硬件安装设置图解1、确认宽带线路正常:无线宽带路由器可以让您将家中的计算机共享高速宽带网络连结至互联网;但在此之前,您必须先具备一部基于以太网络的Cable/DSL Modem(使用RJ-45 接头),并确定您的宽带网络在只有连接…
教你如何编写第一个爬虫
2019年不管是编程语言排行榜还是在互联网行业,Python一直备受争议,到底是Java热门还是Python热门也是一直让人争吵的话题。随着信息时代的迭代更新,人工智能的兴起,Python编程语言也随之被人们广泛学习,Python数据分析…

【BZOJ】3542: DZY Loves March
题意 \(m * m\)的网格,有\(n\)个点。\(t\)个询问:操作一:第\(x\)个点向四个方向移动了\(d\)个单位。操作二:询问同行同列其他点到这个点的曼哈顿距离和。强制在线。(\(n \le 10^5,m \le 10^{18}\)ÿ…

Gin源码解析和例子——路由
Gin是一个基于golang的net包实现的网络框架。从github上,我们可以看到它相对于其他框架而言,具有优越的性能。本系列将从应用的角度来解析其源码。(转载请指明出于breaksoftware的csdn博客) 本文我们将分析其路由的原理。先看个例…
一文讲透推荐系统提供web服务的2种方式
作者丨gongyouliu编辑丨zandy来源 | 大数据与人工智能(ID: ai-big-data)推荐系统是一种信息过滤技术,通过从用户行为中挖掘用户兴趣偏好,为用户提供个性化的信息,减少用户的找寻时间,降低用户的决策成本&am…

jQuery遍历json数组怎么整。。。
{"options":"[{\"text\":\"王家湾\",\"value\":\"9\"},{\"text\":\"李家湾\",\"value\":\"10\"},{\"text\":\"邵家湾\",\"value\":\"13\…

述说C#中的值类型和引用类型的千丝万缕
关于值类型和引用类型方面的博客和文章可以说是汗牛充栋了,今天无意中又复读了一下这方面的知识,感觉还是有许多新感悟的,就此时间分享一下: CLR支持两种类型:值类型和引用类型,看起来FCL的大多数类型是引用…

Gin源码解析和例子——中间件(middleware)
在《Gin源码解析和例子——路由》一文中,我们已经初识中间件。本文将继续探讨这个技术。(转载请指明出于breaksoftware的csdn博客) Gin的中间件,本质是一个匿名回调函数。这和绑定到一个路径下的处理函数本质是一样的。 再以Engin…

DNS简单配置
DNS的原理就不说了,这里只是做个简单的配置,也是方便自己记忆,在这里还要十分感谢redking老大的教程!要安装的bind* 、caching-nameserver 包1、/var/named/chroot/etc/named.conf这个文件需要自己创建options { listen-on…
关系抽取论文整理,核方法、远程监督的重点都在这里
来源 | CSDN 博客作者 | Matt_sh,编辑 | Carol来源 | CSDN云计算(ID:CSDNcloud)本文是个人阅读文章的笔记整理,没有涉及到深度学习在关系抽取中的应用。笔记中一部分来自个人解读,一部分来自原文࿰…

freemarker内建函数介绍
Sequence的内置函数1.sequence?first 返回sequence的第一个值。2.sequence?last 返回sequence的最后一个值。3.sequence?reverse 将sequence的现有顺序反转,即倒序排序4.sequence?size 返回sequence的大小5.sequence?sort 将sequence中的对象转化为字符串后顺序…

PowerBuilder 11.x 的重要进步和不足
PowerBuilder 11(以下简称PB)出来有一段时间了,但很多用户对PB11的到底有哪些进步还不是很清楚,由于对PB11缺乏了解和信心,目前用PB11做出像样应用的用户不多,这确实非常遗憾,这里我讲一下我对P…
超赞的PyTorch资源大列表,GitHub标星9k+,中文版也上线了
点击阅读原文,快速报名!作者 | 红色石头来源 | AI有道(ID: redstonewill)自 2017 年 1 月 PyTorch 推出以来,其热度持续上升。PyTorch 能在短时间内被众多研究人员和工程师接受并推崇是因为其有着诸多优点,…

C++拾取——Linux下实测布隆过滤器(Bloom filter)和unordered_multiset查询效率
布隆过滤器是一种判定元素是否存在于集合中的方法。其基本原理是使用哈希方法将数据映射到一个很长的向量上。在维基百科上,它被称为“空间效率和查询时间都远远超过一般的算法”的方法。由于它只保存散列的数据,所以对于很长的数据有着良好的压缩特性&a…