stl 不熟悉的算法 algorithm
1.nth_element (a,a+n,a+m,cmp)
cmp 是一个比较函数
(这里 a+n,a+m 分别对应首迭代器 尾迭代器)
必须支持·随机访问迭代器的容器才能使用 当然数组也可以
用途 选择出 这个容器中第(n+1)小的元素
在他前的元素比他小 后面比他大 但是不一定有顺序 可以a[n]取出元素(字符串也可以)
2.next_permutation 和 previous_permutation
bool next_permutation (BidirectionalIterator first, BidirectionalIterator last, Compare comp);
comp 也可省
字典顺序
【用法总结】C++ STL中 next_permutation函数的用法_荷叶田田_的博客-优快云博客
我之前总结过一次 但是可能是操作失误 没保存下来 就看别人的劳动成果吧
3.remove (迭代器a,迭代器b,待删除元素c)
STL函数——remove函数_SinHao22的博客-优快云博客
这位博主讲的很好还讲了 remove与erase的区别
erase iterator <T>::erase(iterator begin, iterator end); void <T>::erase(iterator begin , iterator end);
有成员函数和非成员函数两个版本
大量删除元素时 采用区间erase
remove_if 可以针对判别式进行删除
remove_copy_if 拷贝到新容器 再与老容器互换
4.unique
iterator unique(iterator it_1,iterator it_2,bool MyFunc);
返回其尾迭代器
将相邻的相同元素“合并”,伪删除 与remove相似
STL函数——unique函数_stl unique_初学者清水的博客-优快云博客
删除重复元素
4.rotate
非成员函数
template <class ForwardIterator> ForwardIterator rotate (ForwardIterator first, ForwardIterator middle, ForwardIterator last);
(首迭代器,中迭代器,尾迭代器)
将中迭代器对应元素提升到首迭代器对应位置
如果超出区间则会显示 Segmentation fault
rotate_copy() template <class ForwardIterator, class OutputIterator> OutputIterator rotate_copy (ForwardIterator first, ForwardIterator middle,ForwardIterator last, OutputIterator result); rotate_copy(a.begin(),a.begin()+3,a.end(),ostream_iterator<int> (cout,“ ”));
使用一个输出迭代器 可以自己直接打印序列
5.reverse
0.algorithm 里的反转函数接口:reverse(first,last) 参数为容器的迭代器起始位置和终止位置
1.string和vector和deque只能使用模板库算法里的反转函数
2.list可以使用算法里的和list类的reverse
3.stack和queue没有迭代器,自然不能使用算法里的reverse,其类也没有提供反转的成员函数4.set和map的元素是按照键值排序的,不能修改键值,不可反转
6.assign 赋值
void assign(const_iterator first,const_iterator last);
第一个相当于拷贝函数,把first到last的值赋值给调用者,注意区间的闭合,即:将区间 [first,last) 的元素赋值到当前的 vector 容器中
(不同容器间的拷贝也是可行的 但我没有尝试过所有的容器 并且不同的平台stl也存在差异 尽量同容器使用吧)
void assign(size_type n,const T& x = T());
第二个是把n个x赋值给调用者,即:赋 n 个值为 x 的元素到 vector 容器中,并且清除掉 vector 容器中以前的内容
这两个都是成员函数
7.copy
template <class inputIterator, class outputIterator> outputIterator copy(inputIterator first1, inputIterator last, outputIterator first2);
(容器一的首迭代器,容器一的尾迭代器,容器2的首迭代器)
用于拷贝 和assign很相似 但它是非成员函数(目前我没去实验有太多不同的地方 有机会再补充)
注意: 所有的首/尾迭代器 都只是一个迭代器 为了方便表示区间 我这样记录 实际上不越界就行 (当然说不定越界也会产生很奇妙的反应 大概率会是内存泄露吧)
- insert

四种用法如上图 为成员函数
对vector容器一次插入大量元素 使用区间insert更加高效(不用多次调用insert函数 多次移动vector元素 多次扩展vector容器)
C++ STL vector插入元素(insert()和emplace())详解
里面也有emplace的用法
9.list的成员函数 splice
void splice (iterator position, list& x); void splice (iterator position, list& x, iterator i); void splice (iterator position, list& x, iterator first, iterator last);
position:指向目标列表中要插入元素的位置的迭代器。
x:指向源列表的迭代器。
i:指向源列表中要移动的元素的迭代器。
first 和 last:指定源列表中要移动的元素的范围。
这篇博客讲的很好!
10.
小技巧 使用swap来除去多余内存

这个 shrink-to-fit 我在源码中见过
在swap发生后 原先指向某容器中元素的迭代器,指针和引用依然有效 并指向同样的元素-但这些元素已经在另一个容器内了
- less_equal
template <class T> struct less_equal { bool operator() (const T& x, const T& y) const { return x<=y; }
- equal_range 二分查找
必须有序
非成员函数
inline pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value) { return __equal_range(first, last, value, distance_type(first), iterator_category(first));
(这个__equal_range()是源码当中的内容 详细的需要学习源码)
equal_range(首迭代器, 尾迭代器, 要查询的元素);
注意:这个返回的是pair容器
vector<int> a{1,2,3,3,3,3,4,5,7,8,9}; auto i=equal_range(a.begin(),a.end(),3);
i.first 是一个迭代器 如果没有这个元素则指向下一个元素的位置
i.second 指向下一个元素 也就是 相邻排序的元素
这个迭代器可以+-n 随机迭代器
也就是说这个序列中 i.first 指向第一个3
而i.sceond 指向4
这篇博客有介绍
成员函数
该函数主要在unordered_map
C++中的unordered_map用法详解_zou_albert的博客-优快云博客
上面是 unordered_map 介绍
(我在初始化的时候发现键可以重复 这点了解还很少 要记得研究)
unordered_map<int,string> b={{1,"qw"},{3,"we"},{3,"er"},{3,"rt"},{4,"ty"}}; cout<<b.equal_range(1).first->first;
(感觉好复杂qwq)
13.lower_bound,upper_bound
有点类似equal_range
看这篇博客
equal__range 使用了这两个函数
14.pair
#include <utility> template <class T1,class T2> struct pair
pair将一对值(T1和T2)组合成一个值
这一对值可以具有不同的数据类型(T1和T2), 两个值可以分别用pair的两个公有函数first和second访问。
first ,second 都不用+();
可以直接初始化 也可以未初始化再使用make_pair(v1, v2);
来进行赋值
可以用tie来接受pair对象;
std::tie(name, ages) = getPreson();
getPerson()返回一个pair对象
- advance 非成员函数
template<class InputIterator, class Distance> inline void advance(InputIterator& i, Distance n) { typedef typename iterator_traits<InputIterator>::iterator_category category; __advance(i, n, category()); //重载时,编译期已经能确定调用哪个函数 }
相当于a+n 但更安全 效率取决于迭代器的类型;
16.distance 非成员函数
template<class InputIterator> inline typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last) { typedef typename iterator_traits<Iterator>::iterator_category category; return __distance(first, last, category()); }
返回两个迭代器之间的距离(可以是负数)
这里的两个迭代器可以是任意类型 但仍可能会导致某些错误

使用advance与distance 来安全的实现const_iterator 到iterator 的“转换” 实际上是一个新的迭代器 得到了旧迭代器的地址
17.base 成员函数
reverse_iterator.base()
可以让反向迭代器得到其对应位置的正向迭代器

但其得到的迭代器却不一定指向反向迭代器所指的位置


18.istream_Iterator 与 istreambuf_iterator


这就是两者的最大区别 我不太会总结
19.transform 成员函数
有两种重载
template<class_InIt, class _OutIt, class _Fn1> inline _OutIt_Transform(_InIt _First, _InIt _Last,_OutIt _Dest, _Fn1 _Func) { for(; _First != _Last; ++_First, ++_Dest) *_Dest= _Func(*_First); return(_Dest); }
从参数可看出InIt表示这个算法接收的迭代器类型为输入迭代器类型。参数需要需要容器开始迭代器_First,结束迭代器_OutIt,标识被拷贝容器元素区间,将这个区间中的元素拷贝到_Dest迭代器中所表示的容器中。这里要注意,目标容器中一定要有足够的空间。最后一个参数是一个函数对象或者普通函数,接收容器中的元素作为参数,我们可在此函数中对原容器中元素进行运算,将运算结果插入到目标容器中。
template<class_InIt1,class _InIt2,class _OutIt,class _Fn2> inline _OutIt_Transform(_InIt1 _First1, _InIt1 _Last1,_InIt2 _First2, _OutIt _Dest, _Fn2_Func) { for(; _First1 != _Last1; ++_First1, ++_First2, ++_Dest) *_Dest= _Func(*_First1, *_First2); return(_Dest); }
这个版本的transform算法可将两个容器中的元素经过Func运算存储到目标容器中。
都是看的人家博客 STL-transform算法_我的一亩三分地儿的博客-优快云博客
另一篇博客 有一些细节上的补充 C++ transform(STL transform)函数用法详解