STL

    科技2022-08-19  121

    STL

    standard template library 标准模板库

    template: 模板

    将类型抽象化 将类型和算法分离 编写更加彻底抽象的算法 \函数\类

    1.函数模板 语法规则: template<typename T,…> 函数

    函数模板 给类型之后实例化 模板函数 才生成对应类型的那个函数

    对于某些特殊类型的,函数模板不一定适用,所以需要函数模板特化 (特殊处理) 函数模板全特化

    2.类模板

    template<typename T,…> class 类{

    };

    类模板 --> 实例化 --> 模板类

    (1)类模板全特化 全特化 意味着 整个类所有的成员 和 方法都需要重新写一遍,即使一些成员和方法一模一样 template<> class 类名<特化的类型>{

    }; (2)类模板成员特化 只针对某些成员方法进行特化处理 对于不需要进行特化理的不需要重新写过 template<> 返回值类型 class_name<特化的类型>::mem_name(形参列表){

    } (3)类模板的偏特化 函数模板不支持偏特化 针对类型参数相同 或者 针对 类型的指针 和 数组 进行局部特化 在实例化模板时,需要避免产生歧义

    数据结构与算法 用模板实现是最好的

    模板的类型可以有默认类型 模板可以有非类型参数 template

    模板的非类型参数在实例化必须是常量表达式

    在模板定义中 typename和class 可以互换

    C++提供了很多类模板 函数模板 STL

    STL:

    容器、迭代器、函数对象、通用算法

    十大容器:

    1.线性容器 vector: 向量 list: 列表 deque: 双端队列 2.容器适配器 queue: 队列 stack: 堆栈 properity_queue: 优先队列 3.关联容器 map: 映射 multi_map: 多重映射 set: 集合 multi_set: 多重集合

    *所有容器的共同特点:

    1.支持自动扩容 2.支持深拷贝 拷贝复制 和 拷贝赋值 3.支持 == 和 != 如果认为两个容器相等,则容器容量相等,且相同位置的元素也相等 4.往容器中存储元素时,是存储元素的副本(拷贝构造) 5.容器如果要支持sort 自定义类型需要重载< 或者提供比较的函数对象 如果要支持find或者remove 则需要支持==比较
    vector: 向量
    特点: 1.内存连续 2.支持随机访问 [] 3.在末尾增加元素效率高 4.支持自动扩容 方法: 1.构造函数 vector(); //容量为0 元素为0 vector( size_type num, const TYPE &val );//容量为num,元素个数num, 所有的元 素都是val vector( const vector &from );//拷贝构造 vector( input_iterator start, input_iterator end );//[start,end) 区间的元素来构造
    2.向量容量及元素个数
    size() 向量在元素的个数 capacity() 向量在没有扩容之前容量的大小 empty() 向量是否为空

    3.改变向量容量 和 元素个数

    reserve() 设置Vector最小的元素容纳数量 一般只能扩大,不能变小 只增加内存 不增加元素个数 resize() 设置vecotr中元素的个数 可增多 可减少 (类类型成员增加时调用无参构造和拷贝构造 减少调用析构) 改变元素的个数 也可以间接改变 容量大小 可以对新增加的元素指定 默认为"零" 或者调用无参构造 clear() 清空元素 容量不变
    4.支持==和!=
    两个vectors被认为是相等的,如果: 1.它们具有相同的容量 2.所有相同位置的元素相等.
    5.assign 对向量元素赋值 清除赋值之前的元素
    6.[]和at front back 返回引用
    支持下标访问 [] 可能会越界访问 并不一定会报错 把越界访问的问题隐藏了 at 如果越界 直接抛出异常 可以用try-catch捕获 front() back() 如果没有则出错
    7.增加元素
    push_back() 在末尾增加一个元素
    8.删除元素
    pop_back() 删除末尾的元素
    9.插入元素
    iterator insert( iterator loc, const TYPE &val ); void insert( iterator loc, size_type num, const TYPE &val ); void insert( iterator loc, input_iterator start, input_iterator end );
    10.迭代器
    正向迭代器:begin() end() begin() 返回的是指向第一个元素的迭代器(指针) end() 返回最后一个元素的下一个迭代器(指针) 反向迭代器:rbegin() rend()
    11.erase 删除
    根据迭代器删除 iterator erase( iterator pos ); iterator erase( iterator start, iterator end ); 返回最后删除元素的下一个元素迭代器

    swap 交换

    12.遍历
    for(int i=0;i<v.size();i++){ v[i] v.at(i) } for(int& i:v){ } for(vecotr<int>::iterator it=v.begin();it!=v.end();++it){ *it }
    13.查找
    全局函数 find template<typename IT,typename T> IT find(IT begin,IT end,T key){ for(IT it=begin;it!=end;it++){ if(*it == key){ return it; } } return end; }
    14.排序
    全局函数 sort template<typename IT> void sort(IT begin,IT end){ for(IT it = begin; it != end;it++){ for() } } template<typename IT,typename CT> void sort(IT begin,IT end,CT comp){ }
    list: 列表

    全局的sort函数不支持list 因为list的内存不连续 list的迭代器不支持减法运算

    特点:
    1.内存不连续 2.访问时间复杂度 O(n) 3.在任何位置插入和删除效率都比较高

    比vector多了 push_front() pop_front() back() front()

    (1)merge 合并两个列表 把另外一个列表的元素比较插入到当前列表 如果两个列表有序 merge 有序 (2)erase 删除迭代器指定的元素 返回删除最后一个元素的下一个元素的迭代器 vector<int> v(10,10); vecotr<int>::iteartor it = v.begin(); for(;it!=v.end();it++){//两个连续的10 ,只能删除一个 if(*it == 10){ v.erase(it); } } list<int> l(10,10); list<int>::iterator it = l.begin(); for(;it!=l.end();it++){//核心段错误 if(*it == 10){ l.erase(it); } } (3) remove 删除值相等的对象 == 对象需要重载==运算符 remove_if 按指定条件删除 class Com{ private: int no; public: Com(int no):no(no){} bool operator()(const Emp& e){ //返回true删除 return e.no == no; } }; Com(10) (4) reverse 逆序 (5) sort 排序 list不可以用全局的sort函数 (6) splice 把另外一个列表或者迭代器区间的元素合并到当前list (7) unique 删除连续重复元素只保留一个 不连续的并不判断 按指定条件删除 class Com{ public: bool operator()(const T& pre,const T& curr){ //pre是前一对象 curr是当前对象 如果返回true 则把curr对象从列表中删除 } }; (8) list不支持随机迭代 正向迭代器 和 反向迭代器 支持 ++ -- * 不支持+ 和 -
    3.deque 双端队列
    和vector相似 但它允许在容器开头位置进行快速的插入和删除 比vector多了push_front() 和 pop_front()

    容器适配器:

    对list,vector和deque进行了封装,只提供了某些接口(函数)

    容器适配器: 都可以指定底层的实现 所谓适配 就是提供满足数据结构的接口

    4.stack 堆栈 先进后出
    empty() push() pop() size() top() stack<元素的类型,底层实现的类型>
    5.queue 队列
    底层实现不能是vector 在两端进行操作 empty() push() 调用底层实现的push_back() pop() 调用底层实现的pop_front() 因为vector没有pop_front 所以vector不能作为queue的底层 front() back() size()
    6.priority_queue 没有自己的头文件 和 queue共用头文件
    优先队列在push元素时,相当于插入排序一样 插入到指定位置 对数据进行排序 排在最后面的优先级更高(优先出队列) 底层实现不能是list priority_queue<元素类型,底层实现类型,优先指定类型> 优先指定类型 默认是要怕元素类型的 < 底层实现类型 默认是deque 把学生对象放到优先队列中 要求每次取出来的都是学习成绩最好的那个学生 如果成绩一样,取学号较小

    关联容器:

    底层是红黑树
    7.map 映射
    查找效率高 map 存储的是 (KVP key-value pairs) 键值对 类似于python中的字典 key唯一 根据key来构建红黑树 pair<key_type,value_type> p; 构造pair对象: 直接调用构造函数: pair<key_type,value_type> p(key,value); 调用函数返回一个: make_pair<key_type,value_type>(key,value); pair对象如何访问key和value pair里面有两个成员: first second map<key_type,value_type,comp_type> (1)insert 把pair对象插入到map中,如果key重复 则插入失败 返回 pair<iterator,bool> 类型对象 iterator迭代器指向插入的这个元素 bool 表示插入是否成功 mapobj[key] = value; 如果key不存在则往映射中插入key-value pair 如果key存在则更新value的值 (2)find 根据key查找 不是根据value find在比较时不是调用==进行比较 而是调用<进行比较 它怎么确定是要找的那个key呢? node->key < key || key < node->key == false 表示 node->key == key;
    8.multimap 多重映射
    key值可以重复 因为multimap中可以存在多个key相同的记录,所以不能用 [] pair equal_range(const key_type &key ) 返回一个记录 值等于key的区间 pair第一个迭代器为第一个键==key的记录 第二个迭代器为最后一条键==key的下一条记录
    9.set集合
    只有key没有value key唯一 自定义类型存储到set中需要重载<运算符 find() 根据 < 进行比较 可以指定比较规则 set<元素类型,比较规则类型> 比较规则没有时默认按照元素类型的<
    10.multiset 多重集合
    元素可以重复 在map容器中的key 还是 set窗口中的元素 都不允许修改 因为在一棵有序二叉树中 不允许对节点的元素进行修改
    11.bitset
    二进制位集合
    12.string
    find 没有找到返回 string::npos
    auto 万能类型
    auto ret = func();
    nullptr
    比NULL更能代表空指针
    for循环
    for(auto& val:数组/容器变量){} 容器支持迭代器
    array 数组
    forward_list 单向链表
    list: 双向链表
    unordered_map
    map,multimap,set,multiset 底层是红黑树实现 查找效率O(logn) unordered_map,unordered_set 底层用哈希表实现 O(1) 哈希表最大的缺点: rehash 哈希表在不断地插入和删除之后可以需要重新哈希 内存增长 如果数据固定: 一定是用哈希结构来存储这些数据 能够保证最快的查找效率
    多线程
    #include <thread>
    原子数据类型
    #include <atomic> atomic_int 原子数据类型 操作原子数据类型变量时 相当于底层自动上锁
    线程互斥锁
    #include <mutex>
    条件变量
    #include <condition_variable> 用上述内容实现生产者消费者模型
    智能指针
    auto_ptr shared_ptr weak_ptr
    Processed: 0.012, SQL: 9