欢迎来到CJY的博客|

wenli7363

园龄:3年3个月粉丝:7关注:6

STL 黑马程序员教程

1 概述

1 .1 STL基本概念

  • STL(Standard Template Library)标准模板库
  • STL广义上分为:容器(container)、算法(algorithm)、迭代器(iterator)
  • container 和 algorithm之间通过iterator连接
  • STL采用了模板类和模板函数

1.2 STL六大组件

容器、算法、迭代器、仿函数、配置器(配接器),空间配置器

  1. 容器:

    • 序列式容器:每个元素有固定的位置
    • 关联式容器:二叉树结构,元素没有严格物理上的顺序关系
  2. 算法:

    • 质变算法:运算过程中会更改区间内的元素的内容,另一个就是非质变算法
  3. 迭代器:每个容器有自己专属的迭代器,其中常用的是双向迭代器和随机访问迭代器

2 String

  1. 构造函数
  2. 赋值函数 :①等号重载 ②assign()
  3. 字符串拼接:①+= ②append()
  4. 查找:①find(),从左到右查 ②rfind(),从右到左查 ----最后返回的下标都是从左到右的
  5. 替换: S1.replace(int pos,int n, s2)
  6. 字符串比较 s1.compare(s2)
  7. string中单个字符的存取:①直接用下标S1[INDEX],②s1.at(index)
  8. 插入与删除:s1.insert(int pos,int n,string) s1.erase(int pos,int n)
  9. 子串:string substr (int pos=0,int n=npos) 从[pos,n]的左闭右闭切片
//打印字符串的时候,注意要用c_str(),不然会有乱码
string a ="cjy";
printf("%s",a.c_str()); //c_str()返回当前字符串的首字符地址
//当然,直接按下面这也行
cout<<a<<endl;

3 Vector

  1. 构造函数:

    1. 默认使用模板:vector<T> v,无参构造,后面自己push_back元素进去
    2. vector(v.begin(),v.end()) ,将begin和end间的元素拷贝
    3. 拷贝构造
  2. 赋值:①重载等号②v.assign(beg ,end)v.assign(n,elem)拷贝n个element

  3. empty()

  4. capacity() 容量

  5. size() 当前大小

// 遍历vector容器的方法
vector<int> a;
// 插入
for( int i = 0; i < 10; i++) push_back(i);
// 遍历
for(vector<int>::iterator i = a.begin(); i != a.end(); i++) cout<< *i <<" ";
for(auto i = a.begin(); i != a.end(); i++) cout<<*i <<" ";
for(auto x : a) cout<<x<<" ";
// 支持比较大小,从第一个元素开始依次
vector<int> a(3,4), b(4,3);
if(a<b) puts("Yes");
  1. resize (int num (elem)),变短删去末尾多的,变长用默认值(elem)填充

  2. 插入删除

    1. push_back()
    2. pop_back()
    3. insert(const_iterator pos) 注意insert之后,这里的迭代器位置会发生变化,但仍然指向原来元素
    4. erase(const_iterator pos)
    5. clear() 删除所有元素
  3. 数据存取

    1. at[IDX]
    2. operator[]
    3. front() ----返回容器第一个元素
    4. back() -----返回容器最后一个元素
  4. 互换容器 v1.swap(v2)

    //一个小小的语法糖
    //假设创建了一个很大容量的v1
    vector<int> v(100000);
    v.resize(3);
    //这个时候 哪怕resize了,capacity不变,只是size变了
    //这时候就会浪费很多空间
    //通过与匿名对象swap,更改capacity,节约空间
    vector<int>(v).swap(v)

    先用vector<int>(v)拷贝构造了一个匿名对象,这个对象与v swap之后,capacity和size都变为3。

  5. 预留位置

    reserve(int len); //容器预留len个元素长度,预留位置不初始化,元素不可访问。

    • 主要是因为vector有个动态扩展长度的功能,如果之前开辟空间不够,他会重新自动分配空间给整个vector。预留空间,可以节省这个过程

4 deque(双端数组)

  • deque头部访问速度比vector快

  • deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据

  • 中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间

  • deque容器的迭代器也是支持随机访问的

  1. 构造函数:和vector一样
  2. 赋值:①重载=②assign(begin,end)③``
  3. empty() size() resize() deque没有capacity的概念
  4. deque数据插入与删除
    1. push_back(elem) push_front(elem) pop_back pop_front
    2. insert(const_iterator pos,elem) clear() erase()
  5. 数据存取:
    1. d.at(index)
    2. operator[]
    3. d.front() --返回第一个元素
    4. d.back() --返回最后一个元素
  6. deque排序sort(iterator beg, iterator end) ---对beg和end区间内元素进行排序

5 stack(FILO)

  1. 构造函数 stack<T> stk 拷贝构造stack(stk)
  2. 赋值操作:重载
  3. 数据存取:push(elem) pop() top()
  4. 大小:empty() size()

6 queue (FIFO)

只允许一端进,另一端出

  1. 构造函数
  2. 重载等号赋值
  3. push(elem) pop() back()--取最后一个元素 front() ---取第一个元素
  4. empty() size()

7 List (双向循环链表)

说明: 2015-11-15_225145

双向链表采用双向迭代器,支持前移后移

  1. 构造函数:和vector一样

  2. 赋值: assign(beg,end) assign(n,elem) = swap

  3. size() empty() resize(num) resize(num,elem)

  4. 插入与删除

    • push_back(elem);//在容器尾部加入一个元素
    • pop_back();//删除容器中最后一个元素
    • push_front(elem);//在容器开头插入一个元素
    • pop_front();//从容器开头移除第一个元素
    • insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
    • insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
    • insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
    • clear();//移除容器的所有数据
    • erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
    • erase(pos);//删除pos位置的数据,返回下一个数据的位置。
    • remove(elem);//删除容器中所有与elem值匹配的元素。 A
      • 存取元素:front()返回第一个元素 back()返回最后一个元素 不能用at和【】 原因是迭代器不是随机访问迭代器,而是双向迭代器
  5. 成员函数:L.reverse()翻转链表 L.sort()排序

    注意:所有不支持随机访问迭代器的容器,不可以用标准算法,这些迭代器内部会提供相应的成员函数

    默认采用升序序列排序,要通过函数或仿函数自定义相应的排序规则

    比如 我要写一个降序的回调函数

    bool mycompare(int v1,int v2)
    {
    //降序 让第一个数大于第二个数
    return v1>v2;
    }

8 Set/multiset ----头文件<set>

  • 所有元素在插入时会自动排序,是个关联式容器,底层是以二叉树结构实现
  1. 构造:set<T> st set()拷贝构造

  2. 等号赋值

  3. 数据插入用insert st.insert(elem) clear() erase(pos) erase(beg,end) erase(elem)

  4. size() empty() swap(st)

  5. find(key) 查找key是否存在,若存在则返回该键的元素的迭代器,若不存在,返回end迭代器

  6. count(key) 统计某个key元素的个数 (对set而言,结果要么0,要么1,因为不允许重复)

  7. set和multiset的区别

    1. set不可以插入重复数据,而multiset可以

    2. set插入数据的同时会返回插入结果,表示插入是否成功,以对组形式返回 pair<set<int>::iterator ,bool>,如果插入成功,迭代器指向插入位置,bool值为true

    3. multiset不会检测数据,直接返回迭代器,因此可以插入重复数据

    4. set容器排序:set容器默认排序规则为从小到大,利用仿函数改变排序规则(降序或者是自定义数据类型排序时使用)

      尤其是自定义数据类型,如果不给排序规则,就不能插入set,因为编译器会报错

      //比如我要插入5,4,3,2,1 ;如果直接插入set,是个升序排序,这时候我们要用仿函数
      //定义一个仿函数
      class myCompare{
      public:
      //仿函数简单理解为重载小括号
      bool operator()(int v1, int v2)
      {
      return v1>V2;
      }
      };
      int main(){
      //创建容器的时候带上仿函数的类名即可
      set<int,myCompare> s1;
      s1.insert(1); //后面就随便插入了,会自动根据仿函数规则排序的
      }

9 pair对组

成对出现的数据,也支持按字典序进行比较,比较时以first为第一关键字,以second为第二关键字

创建方式:

  • pair<type,type> p (value1,value2)
  • pair<type,type> p =make_pair(value1,value2)
  • p = {value1, value2}

打印数据p.first p.second 注意这是成员,不是函数

10 map/multimap

简介:

  • map中所有元素都是pair,所以插入元素都是对组
  • pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
  • 所有元素都会根据元素的键值自动排序

本质:

  • map/multimap属于关联式容器,底层结构是用二叉树实现。

优点:

  • 可以根据key值快速找到value值

map和multimap区别

  • map不允许容器中有重复key值元素
  • multimap允许容器中有重复key值元素
  1. 构造:map<T1,T2> mp map(const map&mp)拷贝构造

  2. 重载等号赋值

  3. size(); empty(); swap(st);

  4. 插入删除数据:

  5. insert(pair<int,int>(10,20))

  6. clear()

  7. erase(pos迭代器)

  8. erase(bed,end) -----返回下一个元素的迭代器

  9. erase(key) ----删除值为key的元素

  10. 查找与统计:

  11. find(键) ----若键存在返回该键的元素的迭代器

  12. count(key) 统计元素个数

  13. 排序:同set,自定义仿函数进行排序


STL-函数对象/仿函数

1.概念:

  • 重载__函数调用操作符__的类,其对象被称为函数对象

  • 函数对象使用重载的()时,因为其行为像个函数,所以也叫仿函数

  • 本质:仿函数本质是个类,不是一个函数

class MyAdd{
public:
int operator()(int a,int b)
{
return a+b;
}
};
void test01() //可以像函数一样传参,有返回值
{
MyAdd myadd; //因为是个类,还是要先实例化对象
cout<<myadd(10,10)<<endl;
}

因为本质上是个类,所以可以有自己的成员变量来记录状态

class MyAdd{
public:
int operator()(int a ,int b)
{
return a+b;
}
int cnt=0 //记录调用次数
};

仿函数可以做为函数参数传递 类似python中的lambda函数

void doAdd(MyAdd &m)
{
cout<<m.cnt<<endl;
}
void test03(){
MyAdd myadd;
doAdd(myadd);
}

2. 谓词

2.1 谓词的概念

  • __返回bool类型的仿函数__称为谓词
  • 如果operator()接受一个参数,就叫做一元谓词
  • 如果接受两个参数,就叫二元谓词

一元谓词举例

class GreaterFive{
bool operator()(int val) //只有一个参数
{
return val>5;
}
};

3. 内建函数对象

引入头文件#include<functional>

STL内建了一些函数对象,分为算术仿函数、关系仿函数、逻辑仿函数

这些仿函数产生对象,用法与一般函数完全相同。

3.1 算术仿函数

功能描述:

  • 实现四则运算
  • 其中negate是一元运算,其他都是二元运算

仿函数原型:

  • template<class T> T plus<T> //加法仿函数
  • template<class T> T minus<T> //减法仿函数
  • template<class T> T multiplies<T> //乘法仿函数
  • template<class T> T divides<T> //除法仿函数
  • template<class T> T modulus<T> //取模仿函数
  • template<class T> T negate<T> //取反仿函数

调用过程

void test()
{
//创建仿函数对象
negate<int> a;
plus<int> b;
//像调用函数一样去使用
cout<<a(50)<<endl;
cout<<b(20,10)<<endl;
}

3.2 关系仿函数

仿函数原型:

  • template<class T> bool equal_to<T> //等于
  • template<class T> bool not_equal_to<T> //不等于
  • template<class T> bool greater<T> //大于
  • template<class T> bool greater_equal<T> //大于等于
  • template<class T> bool less<T> //小于
  • template<class T> bool less_equal<T> //小于等于

3.3 逻辑仿函数

函数原型:

  • template<class T> bool logical_and<T> //逻辑与
  • template<class T> bool logical_or<T> //逻辑或
  • template<class T> bool logical_not<T> //逻辑非
posted @   wenli7363  阅读(26)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起