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. [LeetCode] 470. Implement Rand10() Using Rand7()

    Given a function rand7 which generates a uniform random integer in the range 1 to 7, write a functio ...

  2. MongoDB 学习笔记之 删除数据,集合,数据库

    删除数据,集合,数据库: 删除一个文档: db.media.deleteOne({"name": "Sky"}) 删除多个文档: db.media.delete ...

  3. GoLang 获取两个时间相差多少小时

    package main import ( "fmt" "time" ) func main() { fmt.Println(getHourDiffer(&qu ...

  4. Python多任务之协程

    前言 协程的核心点在于协程的使用,即只需要了解怎么使用协程即可:但如果你想了解协程是怎么实现的,就需要了解依次了解可迭代,迭代器,生成器了: 如果你只想看协程的使用,那么只需要看第一部分内容就行了:如 ...

  5. 算法学习之剑指offer(八)

    题目一 题目描述 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没 ...

  6. powershell 基础

    目录 本教程概述 用到的工具 标签 简介 0x01使用简介 0x02脚本编写 0x03实例讲解 本教程概述 本课我们学习powershell使用. 用到的工具 cmd.exe   powershell ...

  7. SQL Server Try Catch 异常捕捉

    SQL Server Try Catch 异常捕捉 背景 今天遇到一个关于try catch 使用比较有意思的问题.如下一段代码: SELECT @@TRANCOUNT AS A BEGIN TRY ...

  8. [CF722C] Destroying Array

    C. Destroying Array time limit per test 1 second memory limit per test 256 megabytes input standard ...

  9. Kubernetes的Service运行原理

    一.为什么Servcie能定位到Pod 因为Pod的IP是不固定的,所以Kubernetes需要Service,除此之外它还可以在多个Pod间负载均衡 Service的访问入口,其实是宿主机的kube ...

  10. idea迁移到其他电脑,省去重新安装破解及配置

    idea迁移到其他电脑,省去重新安装破解及配置,要求路径与之前的电脑保持相同. 1. 将idea的配置目录文件夹整个复制过去,默认路径 C:\Users\Administrator\.IntelliJ ...