STL又叫标准模板库,提供各种容器。

STL是C++一部分,不休要额外安装什么,它被内建在编译器之内。

STL重要特点是,数据结构和实现分离。

*所谓迭代器,类似一个游标,使用++指向下一个元素,使用--指向前一个元素。实际上“迭代器”是一个对象,封装了指针,重载了操作符。

1.  动态数组,可变数组

#include<vector>//存放容器的

#include<algorithm>//STL的算法

void CallBackPrintVector(int v)//因为知道迭代器是vector<int>,所以形参为int

{

  cout<<v<<end;

}

int main()

{

  vecotor<int>  v;

  v.push_back(10);//添加元素

  //通过STL提供的算法,进行遍历。容器提供迭代器,迭代器作为for_each参数。v.begin()提供一个开始的迭代器。

     vector<int> ::iterator pBegin = v.begin();// vector<int> ::iterator可能是内部类。begin是指向第一个元素

     vector<int> ::iterator pEnd = v.end();//end是指向最后一个元素,再后一个位

  for_each(pBegin , pEnd , CallBackPrintVector) ;

   //for_each其实是一个算法, 传入beign和end,实质上是为了判断什么时候结束迭代。传入回调函数,是每次迭代都触发。

  //也可以:

  for(vector<int> ::iterator  it=pBegin; it!=pEnd; it++)

  {

    CallBackPrintVector(*it);//应该是重写了*号操作符。

  }

}

for_each还可以:

class/struct Op{  void operator()(int a) ;}

for_each(pBegin , pEnd , Op()) ;//传入重写()操作符的Op类的匿名对象

//

反向迭代器 v.rbegin(),v.rend()

//

vector实现动态增长:如果空间不足,会重新申请更大的内存,将原空间的数据拷贝到新空间,再将新元素插入。所以叫动态数组。

//

v.size();//返回元素个数;

//

v.resize(10,(重载)多出来部分的默认值);//如果容器变短,那么超出的元素被剔除;

//

v.empty();//判断是否为空;

//

v.capacity();//获取容量,根据插入原理,每次都拷贝数据到新空间,会很低效,所以有大于size的容量;

//

vector支持随机访问,意思是,v.insert(v.begin()+2,100);//v.begin()+2就是随机访问,可以任意跳。其他容器就不一定了,可能只能进行++操作

//

vector在删除的时候,并不会自动收缩内存区域,所以要 verctor<int>(v).swap(v)   ,以收缩空间。首先,vector<int>(v),是以v来实例化一个匿名的对象,长队和v一样,然后vector<int>(v).swap(v),将匿名对象的指针,和v交换。也可以v.resize()

//

v.reserve(10000);//在调用push_back前预留空间,这样子的话,就不需要在空间不够的时候,重新开辟,然后拷贝了。只是开辟内存空间,没有初始化的。

//

2. string容器

char *是指针,string是类

string封装了char*,管理这个字符串,是一个char*容器

不用考虑内存释放,越界

int main()

{

  string s1;

  string s2(10,'a');

  string s3("absdfasdf");

  string s4(s3);

  

  for(int i=0;i<s1.size();i++)

  {

    s1[i];//如果用中括号形式,访问越界,直接挂了,没有办法捕获异常。重写了[]符号

    s1.at(i);//访问越界,会抛出异常 out_of_range

  }

}

find()从前往后查找。int index= find("aaa");

rfind()从后先前查找

//字符串比较

if(s1.compare(s2)==0)

{

  //相等

}

//字符串擦除

s.erase(0,2);

//char*转string

int main(){

  char *s = "aaa";

  string sstr(s);

}

//string转char*

int main(){

  string str ="aaa";

  const char* cstr = str.c_str();

}

3. Deque容器

在头部和尾部插入,删除,都很快的容器。

可随机存取,效率高。(应该是连续的内存空间)

.push_back():从尾部插入

.pop_back():从尾部删除

.push_front():从头部插入

.pop_front():从头部删除

.begin() 头部迭代器

.front():返回第一个元素

d1.swap(d2):交换两个空间的元素

#include<deque>

int main()

{

  deque<int> d1;

  deque<int> d2(10,5);//用10个5初始化

  deque<int> d3(d2.begin(),de.end());

  deque<int> d4(d3);

  for(deque<int>::iterator it=d4.begin();it!=d4.end();it++)

  {

    cout<< *it;

  }

  cout<<endl;

}

**排序函数

void print(int e);

int main()

{

  deque<int> de;

  de.push_back(10);

  de.push_back(11);

  //...

  sort(de.begin(),de.end());//排序,应该是跟for_each,是一个在deque头文件中声明的函数

  for_each(de.begin(),de.end(),print);  

  de.pop_front();//删除第一个元素

  de.pon_back();//删除最后一个元素

}

4.  对于sort的特别使用

class Person

{

  public:

  int age;

  string Name;

  Person(int age,char * Name);

}

//排序规则

bool compareCallblack(Person &p1, Person&p2)

{

  return p1.age < p2.age;//这里决定是正序还是倒序,<是从小到大排序

}

int main()

{

  Person p1(1,"tom"),p2(2,"marry");

  Vector ps ;

  ps.push_back(p1);

  ps.push_back(p2);

  sort(ps.begin(),ps.end(),compareCallblack);

}

5. stack 容器,先进后出的容器

push():压栈

pop():出栈,删除最后入栈的

top():获取栈顶元素

注意:栈不能遍历,不提供迭代器,更不支持随机存取

#include<int>

int main()

{

  stack<int> s1;

  stack<int> s2(s1);

  s1.push(10);

  s1.push(20);

  s1.push(30);//栈顶

  s1.pop();//删除栈顶元素

  while(!s1.empty())

  {

    cout<<s1.top();

    s1.pop();

  }

}

6. queue容器

先进先出,在一端插入,另一端出

push():入队操作

pop():删除队头,即删除最先如队的

front():队头元素,即最先入队的

注意:队列不能遍历,不提供迭代器,更不支持随机存取

int main()

{

  queue<int> q;

  q.push(1);

  q.push(2);

  q.push(3);

  q.push(4);

  while(q.size()>0)

  {

    cout<<q.front();

    q.pop();

  }

}

//输出1234

7. List容器

链表,包含数据域和指针域,链表内存结构是非连续的

添加删除元素,时间复杂度都是常数,不需要移动数据。

链表的内存没有像vector一样,有所预留。

提供迭代器。

List不支持随机访问,一般sort都要支持随机访问的,所以,List自己提供sort算法。

int main()

{

  list<int> mlist;

  list<int> milist2(10,10);

  list<int> mlist3(mlist2.begin(),mlist2.end());

  //

  mlist.insert(mlist.begin(),200);//在从头插入

  mlist.insert(mlist.end(),200);//在尾插入

  //

  mlist.pop_back();//删除最后一个

  mlist.remove(200);//能去除所有200的值,应该有重载,能调像sort一样,删除符合条件的值

  //

  for(list<int>::iterator it=mlist3.begin();it!=mlist3.end();it++)

  {

    cout<< *it;

  }

}

mlist.push_back();//往后插入

mlist.push_front();//往前插入

mlist.sort(compareCallblack);//排序

8. set容器

//是基于二叉树算法的容器,二叉树是用于查找数据的一种优化算法

set只提供insert()方法,因为是自动排序的,所以没有其他方法添加数据

set不能插入重复元素

set要改变元素的值,只能先删除,再插入

int mian()

{

  set<int > s1;

  s1.insert(1);

  //...

  for(set<int >::itertor it=s1.begin();it!=s1.end();it++)

  {

     cout<s1;

  }

}

注意:无论按什么顺序插入,set会根据算法自动排序,所以按顺序插入是没有意义的。而且其遍历方法,分为先序,中序,后序方法。

s.erase(value);//删除

s.erase(s.begin());//

multset容器可以放重复元素,这是与set唯一的区别

//查找

set只有实只(map有key和value(实)值)

s.find(key);//查找key是否存在,如果存在,返回该元素的迭代器,否则,返回s.end(); 注意: end是指向比最后一个元素还要后的位置的

int main()

{

  set<int > s;

  set<int>::interator ret= s.find(4);

  if(ret==s.end())

  {

    cout<<"not found"<<endl;

  }

  //查找大于

  set<int> ::interator s1.lower_bound(2);//找第一个小于等于其值的

  set<int> ::interator s1.upper_bound(2);//找第一个大于等于其值的

  pair< set<int>::iterartor, set<int>::iterartor>  pairIterator = s1.equal_range(2);//返回upper_bound和lower_bound的结果

  pairIterator .first;

  pairIterator .secord;

  if(pairIterator .first==s1.end())

  {}

}

set制定一个排序规则

例一:

//C++坑真多,和sort又不一样了

class mycmopare

{

  public :

    bool operator()(inv v1,int v2)

    {

      return v1>v2;

    }

}

int main()

{

  set<int ,mycmopare> s1;//估计里面自行实例化一个对象,然后调用operator排序

  s1.insert(7);

  s1.insert(6);

}

例二:

class person

{

  public:

    int age;

    string Name;

    person(int age,string name);

}

//仿函数

class mycompare

{

  bool operator()(person &p1, person&p2)

  {

    return p1.age>p2.age;

  }

}

int main()

{

  ser<person,mycompare> sp;//set需要排序,当放对象前,需要告知其排序准则,所以在构造前要模板形式传入

  person p1=person(10,"a"),p2=person(1,"b")

  sp.insert(p1);

  sp.insert(p2);

  for(set<person,mycompare>::iterator it=sp.begin();it!=sp.end();ip++)

  {

    cout<<(*sp).age<<endl;

  }

  //

  p3 = person(1,"c")

  sp.find(p3);//这样是可以查到的,因为是根据mycompare重载()操作符函数,是以age排序的。

}

9.  Map容器

Map会根据Key自动排序,Map封装了pair类;

不支持随机访问

#include<map>

int main()

{

  map<int , int > mymap;

  pair<map<int,int>::iterator,bool> ret = mymap.insert(pair<int,int>(1,1)); //创建匿名的pair<int,int>对象放进去

  //返回迭代器,以及是否成功的pair对象

  if(ret->second)

  {

    cout<<"插入成功"<<endl;

  }

  mymap.insert(make_pair(2,1));

  mymap.insert(map<int,int>::value_type(3,1));

  mymap[40]=40;//第四种构造方式,如果key不存在,那么就插入pair,如果Key存在,就修改value值。如果cout<<mymap[40]<<endl,key不存在的话,也会插入,并赋一个默认值。

  for(map<int,int>::iterator it = mymap.begin();it!=mymap.end();i++)

  {

    cout<<"key:"<<(*it).first<<"value:"<<it->second;

  }

}

//

例二:

class   person

{

  public :

    string Name;

    person(string name):Name(name);

}

struct mycompare//可以写成类,偷懒就写struct

{

  bool operator()(person &p1,person &p2)

  {

    return p1.Name!=p2.Name;  

  }

}

int main()

{

  map<person,int,mycompare> mymap; //由于要自动排序,自定义的数据类型,要告知其排序规则

  mymap.insert(make_pair(person("tom"),20));

}

10. multimap

//multimap的key可以相同,而且相同key的键值,放在连续的存储空间

//类似于部门和员工,Key是部门id

.count(key);//返回key的元素个数

int main()

{

  multimap<int , Worker> workerGroup;

  workerGroup.insert(make_pair(1,Worker("张三")));

  //按组打印

  multlmap<int,worker> ::iterator it = workerGroup.find(1);//返回针对一个Key的迭代器,迭代下去,能遍历这个key的所有value

  int count = workerGroup.count(1);

  for(int i=0;i<count;i++,it++)

  {

    cout<<it->second.workername<<endl;

  }

}

11. 函数元素的深拷贝和浅拷贝

元素是如何放进容器中的?用引用,还是浅拷贝,还是深拷贝?

如果元素存在指针成员,就涉及浅拷贝问题。

元素放到容器中,是进行浅拷贝的,所以,放到容器中的元素,要重写拷贝构造函数、析构函数。

12.  函数对象,仿函数
class A

{

  public :  bool  operator (const  int  &a);

}

int main()

{

  A a;

  a();//仿函数调用,容器也是这个原理,那么就不需要使用函数指针了

}

13. 绑定适配器

#include <vector>

#include<algorithm>

#include<functional>

struct P

{

  void operator()(int v)

  {}

}

int main()

{

  verctor<int> a;

  a.push_back(1);

  //..

  for_each(a.being(),a.end(),P());//传入一个重写()操作符的匿名对象

}

//但是,因为operator只能传一个参数,而且这个参数是for_each内赋值的,要想传多一个参数,那么:

struct Pp:public binary_function<int,int,void> //这里第一个int应该是int v中的 ,第二个int是 inv val中的,第三个,应void operator()的void

{

  

  void operator()(int v,int val)

  {}

}

//

for_each(a.being(),a.end(), bind2nd( P() , 1000 ));

//绑定适配器,将一个一元函数对象,变为二元的

猜测:

struct bind2nd

{

  bind2nd(binary_function<int,int,void> p, int val);

  binary_function<int,int,void>  P;

  int val;

  void operator()(int v)

  {

     return P(v,val);

  }

}

14. 取反适配器

not2

struct cmp

{

  bool operator()(int a,int b)

  {

    return a>b;

  }

}

void main()

{

  vector<int> v;

  v.push_back(1);

  //...

  sort(v.begin(),v.end(),cmp());//不传cmp()匿名对象,那么就按升序排了。

}

//使用适配器 not2

struct cmp2:public binary_function<int,int,bool>

{

    bool operator()(int a,int b)

  {

    return a>b;

  }

}

sort(v.begin(),b.end(),not2(cmp2)); //这里的效果是,对cmp2的结果,再取反,又变回从小到大了。

取反适配器not1,针对一元对象

struct cmp3

{

    bool operator()(int a)

  {

    return a>5;

  }

}

vector<int>::iterator it = find_if(v.begin(),v.end(),cmp3());//返回大于5的

//

struct cmp4: public unary_fuction<int,bool>

{

    bool operator()(int a)

  {

    return a>5;

  }

}

//

vector<int>::iterator it = find_if(v.begin(),v.end(),not1(cmp4()));//此时返回小于5的

//

注意,判断方法:

if(it==v.end())

{

  cout<<"not found"<<endl;

}

15. 函数对象适配器

ptr_func

void fun1(int v)

{

 

}

void fun2(int v,int val)

{

 

}

int main()

{

  vector<int> v;

  //..

  for_each(v.begin(),v.end(), ptr_func( fun1));//不传对象也行,传函数名

  //

  for_each(v.begin(),v.end(), bind2ndptr_func( fun2), 10));//不传对象也行,传函数名

}

16. 成员函数适配器

mem_fun_ref(存放的对象),mem_fun(存放的是指针)

如果容器中,存放的是对象,那么for_each中,希望调用类的方法

class person

{

  public:

    string name;

    void show();//不需要传参,因为本身就带person *const this;

}

void main()

{

  vecotor<person> v;

  v.push_back(person("zhangsan"));

  //..

  for_each(v.begin(),v.end(),mem_fun_ref(&Person::show));

}

//如果放的是对象指针

void main()

{

  vecotor<person*> v;

  v.push_back(&(person("zhangsan")));

  //..

  for_each(v.begin(),v.end(),mem_fun(&Person::show));

}

17. 其他函数

find

void int main()

{

  vector<int> v;

  v.push_bakc(10);

  //..

  vector<int>::iterator ret = find(v.begin(),v.end(),8);

  if(ret!=v.end()) { cout<<"found"<<endl;}

  //

}

//

class person

{

  public:

    int id;

    int age;

    person(int id,int age) :id(id),age(age);

    

       bool operator ==(person &p) const // ==必须重载,因为find里面,将匿名对象作为const引用,并调用==操作符重载方法。(const对象,成员方法必须标记为const)

    {

      return p.id==this->id;

    }

}

int main()

{

  vecotor<person> v1;

  v1.push_back(person(1,2));

  v1.push_back(person(2,2));

  verctor<person> ::iterator ret = find(v.begin(),v.end(),p1); //

}

binary_serch 二分查找法

返回bool类型,只能告知有没有找到

int main()

{

  vector<int> v;

  v.push_back(1);

  //..

  bool ret = binary_serch(v.begin(),v.end(),1);

  //

}

adiacent_find

查找相邻重复的元素迭代器

vector<int> :: iterator it=adiacent_find(v.begin(),v.end());

find_if

根据条件,查找第一个

bool cp(int val)

{

 return val > 3;

}

vector<int>::iterator =  find_if(v.begin(),v.end(),cp);//估计传过去,就F()这样的,或TT++这样,*TT这样,直接调传过去的()、++、*这样的操作符函数。

count_if

int  num = count_if(v.begin(),v.end(),cp);

C++学习笔记11_STL的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  4. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  5. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  6. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  7. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记

    今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...

随机推荐

  1. 记录使用echarts的graph类型绘制流程图全过程(一)-x,y位置的计算

    先说下本次案例业务需求,输入2个节点,获取数据后绘制出2个节点间的路径,之前使用的是网状图,但是网状图的效果不佳,需要转换成流程图的模式: 那么如何在不修改数据的情况下,实现类似效果尼? 看了下ech ...

  2. 一个PHP文件搞定微信H5支付

     / 更新于 2018-07-02 / 8 条评论 过年期间也坚持要撸码啊接着给博客除草,在这个小除夕是情人节的一天,祝大家新年快乐,情人节能够顺利脱单~~~ 回归正题,这篇文章介绍一下微信H5支付, ...

  3. Android自动跳过app开屏广告

    跳过开屏广告,体验流畅人生 开屏广告 是应用启动时显示的广告,一般右下角(或右下角)有倒计时跳过,不主动点击就会 等待3到5秒 后再进入App 自动跳过 是跳过应用的开屏广告的App 一图胜千文,来我 ...

  4. 是男人就过八题A_A String Game题解

    题意 给一个字符串\(s\),和\(n\)个子串\(t[i]\),两个人博弈,每次取出一个串\(t[i]\),在后面加入一个字符,保证新字符串仍然是\(s\)的子串,无法操作的人输. 分析 n个子串, ...

  5. centos7.x 将普通用户加入sudoers中,获取sudo执行权限

    centos7.x 将普通用户加入sudoers中,获取sudo执行权限 0 问题由来   你在提起兴致学习的时候,兴冲冲地往黑洞洞的文本窗口输入下一行: [pan@localhost ~]$ sud ...

  6. Linux下mysql相关操作

    Linux下mysql相关操作 1.创建MySQL mysql -u root -p create user 'username'@'%' identified by 'password'; %可以选 ...

  7. MongoDB系列(一):初步理解

    一.简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库 1.易用性 1)MongoDB是一款面向文档的数据库,而不是关系型数据库,因此而有着更好的扩展性. 2)通过在文档中嵌入文档和数组, ...

  8. mpvue 签字组件

    <template> <div > <canvas class='firstCanvas' canvas-id="firstCanvas" @touc ...

  9. Java序列化总结(最全)

    概念 实现 Serializable 接口, 它只是一个标记接口,不实现也能够进行序列化 RMI: 远程方法调用 RPC: 远程过程调用 序列化ID 解决了序列化与反序列出现代码不一致的问题, 不一致 ...

  10. C#输入中文实现转拼音首字母(亲测,字库不全)

    public string GetPYString(string str) { string tempStr = ""; foreach (char c in str) { if ...