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. ELK 学习笔记之 Logstash基本语法

    Logstash基本语法: 处理输入的input 处理过滤的filter 处理输出的output 区域 数据类型 条件判断 字段引用 区域: Logstash中,是用{}来定义区域 区域内,可以定义插 ...

  2. Redis单线程架构以及工作方式

    一.单线程模型 Redis客户端对服务端的每次调用都经历了发送命令,执行命令,返回结果三个过程.其中执行命令阶段,由于Redis是单线程来处理命令的,所有每一条到达服务端的每一条到达服务端的命令都不会 ...

  3. UVA - 11795 Mega Man's Mission

    Mega Man is off to save the world again. His objective is to kill the Robots created by Dr. Wily who ...

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

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

  5. django2.0+连接mysql数据库迁移时候报错

    django2.0+连接mysql数据库迁移时候报错 情况一 错误信息 django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 ...

  6. ES6入门之let和const命令

    前言 大家好,我是一只流浪的kk,当你看到这边博客的时候,说明你已经进入了ES6学习的领域了,从本篇博客开始,我将会将自己学习到ES6的相关知识进行整理,方便大家参考和学习,那么我将带你进入第一节的内 ...

  7. 理解JavaScript中的堆和栈

    这里先说两个概念:1.堆(heap)2.栈(stack)堆 是堆内存的简称.栈 是栈内存的简称.说到堆栈,我们讲的就是内存的使用和分配了,没有寄存器的事,也没有硬盘的事.各种语言在处理堆栈的原理上都大 ...

  8. [网络流 24 题] luoguP2763 试题库问题

    [返回网络流 24 题索引] 题目描述 假设一个试题库中有 nnn 道试题.每道试题都标明了所属类别.同一道题可能有多个类别属性.现要从题库中抽取 mmm 道题组成试卷.并要求试卷包含指定类型的试题. ...

  9. [Luogu3932] 浮游大陆的68号岛

    题目背景 大样例下发链接: https://pan.baidu.com/s/1nuVpRS1 密码: sfxg 浮游大陆的68号岛,位于浮游大陆的边境地带.平时很少有人造访. 岛上被浓厚的森林覆盖. ...

  10. 懒要懒到底,能自动的就不要手动,Hibernate正向工程完成Oracle数据库到MySql数据库转换(含字段转换、注释)

    需求描述 需求是这样的:因为我们目前的一个老项目是Oracle数据库的,这个库呢,数据库是没有注释的,而且字段名和表名都是大写风格,比如 在代码层面的po呢,以前也是没有任何注释的,但是经过这些年,大 ...