博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
STL杂记
阅读量:6606 次
发布时间:2019-06-24

本文共 10795 字,大约阅读时间需要 35 分钟。

  STL介绍:

我所理解的stl:

容器: 是一种数据结构,如list,vector,和deques ,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器;

算法:  是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用;

迭代器:  提供了访问容器中对象的方法。例如,可以使用一对迭代器指定list或vector中的一定范围的对象。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器也可以是那些定义了operator*()以及其他类似于指针的操作符地方法的类对象;

仿函数:  就是一个类里面重载() 所创建出来的对象,叫做函数对象,或者仿函数

迭代适配器(Adaptor): 

空间配制器(allocator): 分配内存的, 偏底层

 

算法的使用介绍

在stl的算法中分为两大块:一个是全局(泛化)的,一个是容器本身所有的

在使用一个算法时首先看你使用的容器中是否有这个算法,如果有的话,就用容器本身有的

(注意不能使用泛化的,因为泛化的可能不能用这个容器,或者没有容器自带的效率高)

如果没有的话,就使用泛化的

注意这几个例子:图片左边是算法的实现,右边是哪个容器本身有这个算法

 

 

count和count_if使用

源码:

/**对谓词为真的序列的元素进行计数。 *  @brief Count the elements of a sequence for which a predicate is true. *  @ingroup non_mutating_algorithms *  @param  __first  An input iterator. *  @param  __last   An input iterator. *  @param  __pred   A predicate. *  @return   The number of iterators @c i in the range @p [__first,__last) *  for which @p __pred(*i) is true.*/template
inline typename iterator_traits<_InputIterator>::difference_typecount_if(_InputIterator __first, _InputIterator __last, _Predicate __pred){ return std::__count_if(__first, __last, __gnu_cxx::__ops::__pred_iter(__pred));}

使用:

//// Created by lk on 18-6-4.//#include 
#include
#include
#include
using namespace std;bool myfun(int i){
return i > 4;}struct myClasss{ bool operator()(int i){
return i > 4;}}myObjj;int main(){ // 泛化的 vector
vec = {
1,2,3,4,5,5,6,3,4}; auto num = count(vec.begin(), vec.end(), 3); cout << "vec中3的个数为"<< num << endl; auto t = count_if(vec.begin(), vec.end(), myfun); auto t2 = count_if(vec.begin(), vec.end(), myObjj); cout << t << " " << t2 << endl; // 结果为3 3 // 容器本身自带的函数 set
s1 = { 1,2,3,4,5}; auto s_num = s1.count(3); cout << s_num << endl; // 1 return 0;}
使用方法

 

find方法:

template
_IIter find(_IIter, _IIter, const _Tp&); template
_FIter1 find_first_of(_FIter1, _FIter1, _FIter2, _FIter2); template
_FIter1 find_first_of(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); template
_IIter find_if(_IIter, _IIter, _Predicate);
find源码
//// Created by lk on 18-6-4.//#include 
#include
#include
#include
using namespace std;namespace luck_count{ bool myfun(int i){
return i > 4;} struct myClasss{ bool operator()(int i){
return i > 4;} }myObjj; int test_count() { // 泛化的 vector
vec = {
1,2,3,4,5,5,6,3,4}; auto num = count(vec.begin(), vec.end(), 3); cout << "vec中3的个数为"<< num << endl; auto t = count_if(vec.begin(), vec.end(), myfun); auto t2 = count_if(vec.begin(), vec.end(), myObjj); cout << t << " " << t2 << endl; // 结果为3 3 // 容器本身自带的函数 set
s1 = { 1,2,3,4,5}; auto s_num = s1.count(3); cout << s_num << endl; // 1 return 0; }}namespace luck_find{bool myFun(int i) { return i > 2;}struct MyClass{ bool operator()(int i) { return i > 2;}}myObj; void test() { vector
vec = { 1,2,3,4,5,5,6,3,2}; auto it = find(vec.begin(), vec.begin()+5, 6); cout << "it是6的迭代器地址" << endl; auto it2 = find_if(vec.begin(), vec.end(), myFun); cout << "use custom functional" << endl; cout << "it2是大于2的迭代器地址" << endl; auto it3 = find_if(vec.begin(), vec.end(), myObj); cout << "use custom object" << endl; cout << "it3是大于2的迭代器地址" << endl; }}int main(){ luck_count::test_count(); luck_find:: test(); return 0;}
使用方法find和count

 

 sort用法

包含仿函数

 

/**使用比较的谓词来排序序列的元素。  *  @brief Sort the elements of a sequence using a predicate for comparison.  *  @ingroup sorting_algorithms  *  @param  __first   An iterator.  *  @param  __last    Another iterator.  *  @param  __comp    A comparison functor.  *  @return  Nothing.  *  *  Sorts the elements in the range @p [__first,__last) in ascending order,  *  such that @p __comp(*(i+1),*i) is false for every iterator @e i in the  *  range @p [__first,__last-1).  *  *  The relative ordering of equivalent elements is not preserved, use  *  @p stable_sort() if this is needed. */template
inline voidsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp){ // concept requirements __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< _RandomAccessIterator>) __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, typename iterator_traits<_RandomAccessIterator>::value_type, typename iterator_traits<_RandomAccessIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));}
sort源码
#include 
#include
#include
#include
#include
namespace luck_sort{ void print(vector
&vec) { for (auto item : vec) cout << item << " "; cout << endl; } bool myfun(int i, int j){ return i > j;} struct myclass{ bool operator ()(int i, int j){ return i < j;} }myObj; // 仿函数对象省略了 void test() { vector
vec = { 1,2,5,6,2,3,0,-3}; sort(vec.begin(), vec.end()); cout << "use default 谓词"<
()); // greater
() 从大到小排序 print(vec); sort(vec.begin(),vec.end(), myfun); cout << "use custom fun" << endl; print(vec); sort(vec.begin(),vec.end(), myObj); cout << "use custom object" << endl; print(vec); cout << endl; }}int main(){// luck_count::test_count();// cout << endl;// luck_find:: test();// cout << endl; luck_sort:: test(); return 0;}
sort用法

 

 

仿函数

仿函数:就是一个类里面重载() 所创建出来的对象,叫做函数对象,或者仿函数

 

有些功能的的代码,会在不同的成员函数中用到,想复用这些代码。

 

1)公共的函数,可以,这是一个解决方法,不过函数用到的一些变量,就可能成为公共的全局变量,再说为了复用这么一片代码,就要单立出一个函数,也不是很好维护。 

 

2)仿函数,写一个简单类,除了那些维护一个类的成员函数外,就只是实现一个operator(),在类实例化时,就将要用的,非参数的元素传入类中

c和c++中的仿函数

1)c语言使用函数指针和回掉函数来实现仿函数,例如排序函数中使用仿函数:

#include 
#include
//int sort_function( const void *a, const void *b); int sort_function( const void *a, const void *b) { return *(int*)a-*(int*)b; } int main() { int list[5] = { 54, 21, 11, 67, 22 }; qsort((void *)list, 5, sizeof(list[0]), sort_function);//起始地址,个数,元素大小,回调函数 for (auto x = 0; x < 5; x++) printf("%d\n", list[x]); return 0; }

2)在C++里,我们通过在一个类中括号的方法使用一个而不是一个普通函数。

#include 
#include
using namespace std; template
class display { public: void operator()(const T &x) { cout<
<<" "; } }; int main() { int ia[]={
1,2,3,4,5}; for_each(ia,ia+5,display
()); //循环遍历数组 return 0; }

仿函数在STL中的定义

 要使用STL内建的仿函数,必须包含<functional>头文件。而头文件中包含的仿函数分类包括

      1)算术类仿函数

               加:plus<T>

               减:minus<T>

               乘:multiplies<T>

               除:divides<T>

               模取:modulus<T>

               否定:negate<T>

#include 
#include
#include
#include
using namespace std; int main() { int ia[]={
1,2,3,4,5}; vector
iv(ia,ia+5); cout<
())<
()(3,5)<
modulusObj; //取模运算 cout<
<
示例

 2)关系运算类仿函数

               等于:equal_to<T>

               不等于:not_equal_to<T>

               大于:greater<T>

               大于等于:greater_equal<T>

               小于:less<T>

               小于等于:less_equal<T>

              从大到小排序:

 
#include 
#include
#include
using namespace std; template
class display { public: void operator()(const T &x) { cout<
<<" "; } }; int main() { int ia[]={
1,5,4,3,2}; vector
iv(ia,ia+5); sort(iv.begin(),iv.end(),greater
()); for_each(iv.begin(),iv.end(),display
()); return 0; }
View Code

 3)逻辑运算仿函数 

       逻辑与:logical_and<T>

       逻辑或:logical_or<T>

       逻辑否:logical_no<T>

 

bind和适配器 

 

如果想要统计和比20大的数,用自带的仿函数不行,又不像自己写,或者自己写,要写很多,所以用适配器,绑定参数,这里是绑定less中的第二个参数原本less中是x>y 现在就变成x>20

这里的调用过程vec的序列中,统计不满足后面的条件的数的个数

Less<int>()是一个临时的仿函数对象(class A ==> A a()) ,不是调用函数 

但是现在bind2nd被改成bind  bind的功能更加强大,绑定很多个参数

 

 

这里主要讲bind的使用

#include 
#include
#include
#include
#include
namespace luck_bind{ // bind(函数对象,仿函数对象, 对象要的参数_1,_2,...) template
void print(vector
&vec) { for (auto item : vec) { cout << item << " "; } cout << endl; }// a function: (also works with function object: std::divides
my_divide;) double my_divide (double x, double y) { return x/y;} struct MyPair { double a,b; double multiply() { return a*b;} }; void test() { // 这句话必须写, 还有functional头文件 using namespace std::placeholders; // adds visibility of _1, _2, _3,... // binding functions: auto fn_five = std::bind (my_divide,10,2); // returns 10/2 std::cout << fn_five() << '\n'; // 5 auto fn_half = std::bind (my_divide,_1,2); // returns x/2 std::cout << fn_half(10) << '\n'; // 5 auto fn_invert = std::bind (my_divide,_2,_1); // returns y/x std::cout << fn_invert(10,2) << '\n'; // 0.2 auto fn_rounding = std::bind
(my_divide,_1,_2); // returns int(x/y) std::cout << fn_rounding(10,3) << '\n'; // 3 MyPair ten_two { 10,2}; // binding members: auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply() std::cout << bound_member_fn(ten_two) << '\n'; // 20 auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a std::cout << bound_member_data() << '\n'; // 10 vector
vec = { 1,5,2,3,4,-1,6}; cout << "bind and bind2nd different"<
(), 4))) << endl; cout << "use bind of count_if"<
(), _1, 4); cout << count_if(vec.begin(), vec.end(), fn); // 小于4的有几个 4个 cout << "\nbind sort" << endl; sort(vec.begin(), vec.end(), less
()); print
(vec); // 模板函数 sort(vec.begin(), vec.end(), bind(less
(), _2, _1)); print
(vec); }}int main(){// luck_count::test_count();// cout << endl;// luck_find:: test();// cout << endl;// luck_sort:: test(); luck_bind::test(); return 0;}
测试_必看

 

转载于:https://www.cnblogs.com/xiaokang01/p/9135647.html

你可能感兴趣的文章
CSS 笔记——背景布局
查看>>
洛谷P1880 石子合并 [NOI1995]
查看>>
angular限制输入框整数和小数的指令
查看>>
www改变GUITexture的贴图
查看>>
Android 类似launcher左右滑动(实例二)
查看>>
【相机篇】从到FlyCapture2到Spinnaker
查看>>
[Leetcode]35. Search Insert Position
查看>>
sicily 1020 Big Integer
查看>>
原生ajax 请求
查看>>
关闭当前的子窗口,刷新父窗口,弹出层提示框
查看>>
Background agent
查看>>
buntu下连接远程Windows服务器
查看>>
注册、订单流程图
查看>>
js随机生成验证码及其颜色
查看>>
将某个目录下的 文件(字符窜) 只将数字过滤出来
查看>>
机器学习之常见机器学习算法---面试之常见机器学习算法简单思想梳理
查看>>
C# 委托和泛型
查看>>
Beginning Silverlight 4 in C#-数据绑定和Silverlight List控件
查看>>
springmvc 404 视图解析器配置错误
查看>>
WinForm窗体更新程序
查看>>