内容简介:比如我们要构建的序列存储的值是1,2,3,4……10000。使用for循环使用std的标准库iota。
关系数列
等差数列
比如我们要构建的序列存储的值是1,2,3,4……10000。
常规写法
使用for循环
std::vector<int> vec;
for (int i = 0; i < 10000; i++) {
vec.push_back(i + 1);
}
简洁写法
使用std的标准库iota。
std::vector<int> vec(10); std::iota(vec.begin(), vec.end(), 1);
使用std标准库的partial_sum,代码量减少了一半。 partial是局部、区间的意思,sum是累加的意思。第1、2个参数是需要被计算的容器起止迭代器,第3个参数是计算结果保存的起始迭代器。它还有第4个参数,用于描述怎么计算的。
std::vector<int> vec(10000, 1); 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] = 1;
std::partial_sum(vec.begin(), vec.end(), vec.begin(), [](const int&a, int b) {return a + 1;});
如果要生成10000,9999,9998……1这样递减的数列,则可以把第一个元素赋值为10000后,传递一个减法lambda表达式
std::vector<int> vec(10000);
vec[0] = 10000;
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));
}
精简写法
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用于判断两个序列是否是同一个序列的不同(或相同)顺序排列。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- three中蒙皮动画(skinnedMesh)的拾取(raycaster)问题
- C++拾取——使用stl标准库实现排序算法及评测
- C++拾取——stl标准库中集合交集、并集、差集、对等差分方法
- C++拾取——Linux下实测布隆过滤器(Bloom filter)和unordered_multiset查询效率
- Unity动态网格简化算法
- 对于css的简化属性
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java Servlet & JSP Cookbook
Bruce W. Perry / O'Reilly Media / 2003-12-1 / USD 49.99
With literally hundreds of examples and thousands of lines of code, the Java Servlet and JSP Cookbook yields tips and techniques that any Java web developer who uses JavaServer Pages or servlets will ......一起来看看 《Java Servlet & JSP Cookbook》 这本书的介绍吧!