复习一下c++ stl的笔记 | 青训营;

84 阅读7分钟

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函数的用法_荷叶田田_的博客-CSDN博客

我之前总结过一次 但是可能是操作失误 没保存下来 就看别人的劳动成果吧

3.remove (迭代器a,迭代器b,待删除元素c)

STL函数——remove函数_SinHao22的博客-CSDN博客

这位博主讲的很好还讲了 remove与erase的区别

erase iterator ::erase(iterator begin, iterator end); void ::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_初学者清水的博客-CSDN博客

删除重复元素

4.rotate

非成员函数

template 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 (cout,“ ”)); 使用一个输出迭代器 可以自己直接打印序列

5.reverse

0.algorithm 里的反转函数接口:reverse(first,last) 参数为容器的迭代器起始位置和终止位置

1.string和vector和deque只能使用模板库算法里的反转函数

2.list可以使用算法里的和list类的reverse

3.stack和queue没有迭代器,自然不能使用算法里的reverse,其类也没有提供反转的成员函数4.set和map的元素是按照键值排序的,不能修改键值,不可反转

t.csdn.cn/3uHsI

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:指定源列表中要移动的元素的范围。

这篇博客讲的很好!

小技巧 使用swap来除去多余内存

这个 shrink-to-fit 我在源码中见过

在swap发生后 原先指向某容器中元素的迭代器,指针和引用依然有效 并指向同样的元素-但这些元素已经在另一个容器内了

less_equal template 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 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

这篇博客有介绍

t.csdn.cn/yR8KM

成员函数

该函数主要在unordered_map

C++中的unordered_map用法详解_zou_albert的博客-CSDN博客

上面是 unordered_map 介绍

(我在初始化的时候发现键可以重复 这点了解还很少 要记得研究)

t.csdn.cn/Tb295

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

看这篇博客

t.csdn.cn/SAdrN

equal__range 使用了这两个函数

14.pair

#include 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::iterator_category category; __advance(i, n, category()); //重载时,编译期已经能确定调用哪个函数 } 相当于a+n 但更安全 效率取决于迭代器的类型;

16.distance 非成员函数

template inline typename iterator_traits::difference_type distance(InputIterator first, InputIterator last) { typedef typename iterator_traits::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算法_我的一亩三分地儿的博客-CSDN博客

另一篇博客 有一些细节上的补充 C++ transform(STL transform)函数用法详解 ———————————————— 版权声明:本文为CSDN博主「飞飞肥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/m0_74051971…