算法和映射
标准库算法
标准库大约提供了80种有用的算法。
挑选的标准算法
r = find(b,e,v) r值想[b:e]中v首次出现的位置
r = find_if(b,e,p) r指向[b:e]中令p(x)为true的第一个元素x
x = count(b,e,v) x为v在[b:e]中出现的次数
x = count_if(b,e,p) x为[b:e]中满足p(x)为true的元素的个数
sort(b,e) 用<运算符对[b:e]排序
sort(b,e,p) 用谓词p对[b:e]排序
copy(b,e,b2) 将[b:e]拷贝至[b2:b2+(e-b)]; b2之后应用足够的空间用哦关于存储元素
unique_copy(b,e,b2) 将[b:e]拷贝至[b2:b2+(e-b)]; 不拷贝相邻的重复元素
merge(b,e,b2,e2,r) 将有序序列[b2:e2]和[b:e]合并,并放入[r:r+(e-b)+(e2-b2)]之中
r = equal_range(b,e,v) r是有序范围[b:e]的一个子序列,且其中所有元素值均为v,本质上是通过二分搜索查找v
equal(b,e,b2) [b:e]和[b2:b2+(e-b)]的所有元素对应相等?
x = accumulate(b,e,i) x是将i与[b:e]中所有元素进行累加的结果
x = accumulate(b,e,i,op) 与accumulate类似,但用op进行求和运算
x = inner_product(b,e,b2,i) x是[b:e]与[b2:b2+(e-b)]的内积
x = inner_product(b,e,b2,i,op,op2) 与inner_product类似,但用op和op2取代内积的+和*
最简单的算法 find()
template<typename In, typename T>
In find(In first, In last, const T& val)
{
while (first!=last&&*first!=val) ++first;
return first;
}
void f(vector<int>& v, int x)
{
auto p = find(v.begin(), v.end(), x);
if (p!=v.end())
{
//我们在v中找到了x
}
else
{
//v中没有x
}
}
auto ch = 'c'; //ch是一个char
auto d = 2.1; //d是一个double
lambda表达式
数值算法
在STL标准库中只有四种数值算法:
x = accumulate(b,e,i)
累加序列中的值,例如,对{a,b,c,d}计算{i+a+b+c+d}。
结果x的类型与初始值i的类型一致。
x = inner_product(b,e,b2,i)
将两个序列的对应元素相乘并将结果累加。例如,对{a,b,c,d}和{e,f,g,h}计算i+a*e+b*f+c*g+d*h。
结果x的类型与初始值i的类型一致。
r = partial_sum(b,e,r)
对一个序列的前n个元素进行累加,并将累加结果生成一个序列。例如,
对{a,b,c,d}将生成{a,a+b,a+b+c,a+b+c+d}
r = adjacent_diffenrence(b,e,b2,r)
对一个序列的相邻元素进行减操作,并将得到的差生成一个序列。
例如,对{a,b,c,d}将生成{a, b-a, c-b, d-c}
关联容器
一个map就是一个(键,值)对的有序序列,你可以基于一个关键字在其中查找对应的值,
流行的和有用的概念似乎总是由很多名称。在标准库中,我们将这类数据结构统称为关联容器(associative container).
标准库提供了8个关联容器:
map (键,值)对的有序容器
set 关键字的有序容器
unordered_map (键,值)对的无序容器
unordered_set 关键字的无序容器
multimap 关键字可以出现多次的map
multiset 关键字可以出现多次的set
unordered_multimap 关键字可以出现多次的unoedered_map
unordered_multiset 关键字可以出现多次的unoedered_set
map
int main()
{
map<string,int> words; //维护(单词,频率)对
for (string s; cin>>s; )
++words[s]; //注意:用string作为words的下标
for (const auto& p:words)
count<<p.first<<":"p.second<<'\n';
}
words["sultan"]
for(string s; cin>>s;)
++words[s]; // 注意:用string作为words的下标
一个map<string, int>的元素是pair<string,int>。 每个pair的第一个元素名为first,第二个元素名为
second,因此输出循环为
for (const auto& p : words)
count << p.first << ":" p.second << '\n';
map概览
映射的实现有很多种方式,但是STL实现映射通常采用平衡二叉搜索树,更具体一些----红黑树。
一颗树由多个节点构成。一个Node保存一个关键字和对应的值,并且指向两个子节点。
若保存关键字值的Node成员的名字为first,二叉搜索树的基本规则是:
left->first < first && first < right->first
即,对每个节点,
它的左子节点的关键字小于本节点的关键字;
而且,本节点的关键字小于它的右节点的关键字。
这棵树仍然遵守每个节点的关键字大于它的左子节点、小于它的右子节点的规则:
显然,map的接口与vector和list是很相似的。最大的不同是在遍历时,map的元素类型为pair<Key, Value>。