zoukankan      html  css  js  c++  java
  • STL 抄袭笔记

    链接www.cnblogs.com/zhouzhendong/p/STL.html

    C++ STL 的一些基础用法

    本文摘抄并整理自cppreference

    前言

    ​ 创建一个空的 vector ,我一直是这样写的:

    vector <int> v;
    v.clear();
    

    ​ 直到后来:

    vector <int> v;
    

    ​ 在 vector 里创建一个 (0cdots n-1) 的数列,我一直是这样写的:

    vector <int> v(0);
    for (int i=0;i<n;i++)
        v.push_back(i);
    

    ​ 直到后来:

    vector <int> v(n);
    iota(v.begin(),v.end(),0);
    

    ​ 我发现我根本不会用 STL,于是我决定去学一学,于是就有了这篇文章。

    ​ 本文介绍一些常用的 STL 。

    ​ 设 a,b 为两个迭代器,接下来默认 [a,b) 表示位于 a~b-1 的迭代器。

    ​ 接下来所有变量名中,it,it1,it2,... 一般代表迭代器,x,v,... 一般代表类型为 int 的值。

    1. vector

    ​ 于是我们从最常用的 vector 开始。

    ​ vector 的实现基于动态数组,结合倍增思想(空间开不下了就全部删掉再开 2 倍)。

    ​ 单次操作复杂度基本都是均摊 (O(1)) 的。

    1.1 初始化

    vector <int> a;//新建一个空的vector 
    vector <int> b(5,3);//新建一个包含 5 个 3 的 vector
    vector <int> c(5);// = vector <int> c(5,0);
    vector <int> d(b.begin()+1,b.end()-1);// 用 [b.begin()+1,b.end()-1) 这一段构成的数组生成 vector 
    vector <int> e(d);// 生成一个和 d 相同的 vector e
    

    1.2 back

    ​ 设 v 为一个 vector v.back() 返回 v 的最后一个元素的引用。

    ​ 例如

    vector <int> v;
    v.push_back(3);
    cout<<v.back()<<endl;
    v.push_back(5);
    cout<<v.back()<<endl;
    

    ​ 的输出结果是

    3
    5
    

    1.3 begin

    ​ 设 v 为一个 vector v.begin() 返回一个迭代器,指向 v 第一个元素。

    1.4 clear

    v.clear() 表示将 v 清空(内存不释放)。

    1.5 end

    ​ 设 v 为一个 vector v.end() 返回一个迭代器,指向 v 最后一个元素的后一个位置。

    1.6 empty

    ​ 设 v 为一个 vector v.empty() 返回一个布尔值,表示 v 是否为空。

    1.7 erase

    vector <int> v(10);
    iota(v.begin(),v.end(),1);
    v.erase(v.begin()+5);//删除 v.begin()+5 这个位置的元素
    v.erase(v.begin(),v.begin()+3);//删除 [v.begin(),v.end()) 这个区间之间的所有元素
    for (auto i : v)
        cout<<i<<" ";
    

    ​ 输出结果为

    4 5 6 8 9 10
    

    1.8 front

    ​ 设 v 为一个 vector ,则 v.front() 返回 v 的第一个元素的引用。

    1.9 insert

    vector <int> v(3,1);
    vector <int> :: iterator it=v.begin();
    it=v.insert(it,2);//在 it 处插入一个 2
    v.insert(it,2,3);//在 it 处插入 2 个 3 ,注意这个语句执行完之后 it 就失效了
    vector <int> u(3,1);
    u.insert(u.begin(),v.begin(),v.end());//在 u.begin() 处插入 [v.begin(),v.end()) 这个范围内的元素
    

    1.10 operator []

    ​ 这个不用说了吧都懂。

    1.11 pop_back

    ​ 设 v 为一个 vector ,则 v.pop_back() 表示弹出 v 的最后一个元素。

    1.12 push_back

    ​ 设 v 为一个 vector ,则 v.push_back(x) 表示在 v 的最后插入一个元素 x 。

    1.13 size

    ​ 设 v 为一个 vector ,则 v.size() 返回当前 v 中的元素个数。

    1.14 resize

    1.15 relational operators

    ​ 判断两个 vector 是否相等的时候,先比较 size(),然后再逐位比较。

    ​ 设 a,b 为两个 vector,判断 a<b 是否成立时,按照字典序判定,也就是从 (a[0],b[0]),(a[1],b[1]),... 开始不断比较。

    ​ 其他的四种比较符直接用以上两种来生成。

    2. set

    从这里开始,和 vector 有相同意义的函数的解释就省略了。

    ​ 接下来默认定义 set <int> S

    ​ 单次操作的复杂度基本都是 (O(log Size)) 的。

    ​ 它的初始化类似于 vector 。

    2.1 begin

    2.2 clear

    2.3 count

    S.count(x) 表示求 S 中 x 元素的出现次数。由于 set 中各个元素互不相同,所以只会返回 0 或 1 。

    ​ 单次时间复杂度 (O(log Size))

    ​ 1000000 次 count 的用时大约在 0.3 秒到 1 秒左右,取决于电脑的运行效率。

    2.4 empty

    2.5 end

    2.6 erase

    ​ 用于删除元素。

    S.erase(it);// 删除 set 迭代器 it 指向的元素。删除完之后这个迭代器就失效了。
    S.erase(x);// 删除元素 x 
    S.erase(it1,it2);// 删除 [it1,it2) 的所有元素 
    S.erase(it,S.end());// 上一种用法的一个实例
    

    2.7 find

    S.find(x) 返回一个迭代器,这个迭代器指向的元素值为 x 。

    2.8 insert

    S.insert(x) 表示在 S 中插入元素 x ,并返回一个 pair <set <int> :: iterator,bool> ,第一个元素表示插入元素 x 之后 x 的迭代器(如果原本就有 x 就返回原来的 x 的迭代器),第二个元素表示这次插入是否有效,如果 x 原先不在 S 中,那么返回 true,否则返回 false。

    S.insert(it1,it2) 表示在 S 中插入 [it1,it2) 的所有元素。

    2.9 lower_bound

    S.lower_bound(x) 返回 S 中指向 大于等于 x 的最小元素 的迭代器。

    2.10 upper_bound

    S.upper_bound(x) 返回 S 中指向 大于 x 的最小元素 的迭代器。

    2.11 size

    2.12 multiset

    ​ multiset 是可重集,也就是说容器内可以有多个相同元素。

    ​ 大部分用法和 set 一样,这里只讲较为不同的。

    ​ 接下来默认定义 multiset <int> S

    ​ 注意 multiset 的常数比 set 大若干倍。

    2.12.1 count

    S.count(x) 返回 S 中元素 x 的个数。

    ​ 这里单次 count 的时间复杂度大约是 (O(log Size + S.count(x))) 的。

    ​ 实测常数不大,设 n = 10000,则在 S 中 insert n 个 1,再 insert 2...n 各一个,再进行 n 次 S.count(1) 的用时大约在一秒左右(不开 O2),取决于电脑的运行效率。

    ​ n=10000 时,实测用时 0.6s 的电脑,在 n = 100000 时大约要 200s,在 n = 1000 时大约要 0.02s 。

    2.12.2 equal_range

    S.equal_range(x) 返回类型为 pair <multiset <int> :: iterator, multiset <int> :: iterator> 第一个元素和第二个元素分别表示 S 中值为 x 的第一个迭代器位置和最后一个迭代器位置的后一个位置。

    2.12.3 erase

    ​ 注意一下 S.erase(x) 的作用是删除 S 中所有等于 x 的元素。

    ​ 所以在要删除一个 x 的时候得写成 S.erase(S.find(x)) ,这样就只会删掉一个迭代器所指向的值。

    2.13 relational operators

    set 和 multiset 以及 vector 类似。 唯一的区别是 set 的顺序是从小到大比较,vector 是按照下标顺序比较。
    

    3. map

    ​ map 常用于离散化,可以当做一个下标可以是任意类型、任意值的数组用。

    ​ 单次操作的时间复杂度基本都是 (O(log Size))

    ​ map 类型的迭代器比较特殊,例如 map <long long,int> :: iterator 指向的就是一个 pair <long long,int> ,表示元素 first 所对应的值为 second。

    ​ map 的初始化也类似于 vector 。

    ​ 接下来默认定义了 map <int,int> Map

    3.1 begin

    3.2 clear

    3.3 count

    Map.count(x) 表示元素 x 的是否被插入过。

    3.4 empty

    3.5 end

    3.6 equal_range

    3.7 erase

    ​ 和 set 中 erase 的用法是一样的。

    3.8 find

    ​ 和 set 中 find 的用法是一样的。

    3.9 insert

    ​ map 的 insert 和 set 的 insert 略有不同。

    ​ map 中 insert 的东西是个 pair,但是 set 中是个元素。

    ​ 其他都是一样的。

    3.10 lower_bound

    3.11 upper_bound

    3.12 operator []

    ​ 这个有用的重载符大概就是用 map 而不用 set 的动机吧!

    Map[x] 返回 Map 中 first 是 x 的那个 pair 的 second 的引用。

    ​ 例如:

    map <int,int> Map;
    Map[233]++;
    Map[-999]+=Map[233];
    Map[233]+=Map[-999];
    Map[123000000]=Map[-999]+Map[233];
    cout<<Map[-999]<<" "<<Map[123000000]<<" "<<Map[233]<<endl;
    

    ​ 输出结果为

    1 3 2 
    

    3.13 size

    3.14 relational operators

    4. unordered_map

    ​ 需要 c++11 或更新的编译器才可以使用。

    ​ 它是一个 Hash 表。

    ​ map 的弱化版,由于实现原理不同,所以 map 的很多功能他没有,但是它有它唯一的优势

    ——单次操作时间复杂度 (O(1))

    ​ 但是实测运行效率只和 map 差几倍而已。

    ​ 手写 Hash 表往往能比它快 6~10 倍。

    ​ 所以这里不展开介绍。

    5. priority_queue

    ​ 优先队列,堆。

    ​ 完全可以使用 set 代替。不同于 set ,它的功能比较弱,不支持删除等一系列操作,单次操作的时间复杂度还是一样的 (O(log Size)),那么它的用处是什么?

    ​ 它常数小。大约是 set 的 0.5 倍。

    ​ 注意优先队列 没有 迭代器。

    ​ 系统默认的优先队列是大根堆。

    ​ 初始化还是和 vector 差不多的。

    ​ 接下来默认定义 priority_queue <int> Q

    5.1 定义

    定义一个 int 类型的大根堆:priority_queue <int> Q1

    定义一个 char 类型的小根堆: priority_queue <char,vector <char>,greater <char> >Q2

    重载比较运算符:

    struct cmp{
        bool operator () (int a,int b){
            //......
        }
    };
    priority_queue <int,vector <int>,cmp> Q3;
    

    5.2 empty

    5.3 pop

    Q.pop() 表示弹出堆顶元素。

    5.4 push

    Q.push(x) 表示将元素 x 加入 Q 。

    5.5 size

    5.6 top

    Q.top() 会返回 Q 的第一个元素。

    6. stack

    ​ 它连 operator [] 都没有,不如手写。

    7. queue

    它连 operator [] 都没有,不如手写。
    

    8. deque

    ​ 它叫做双端队列。

    ​ 在常数要求严格的情况下,deque 会非常好用。

    ​ deque 就像一个升级版 vector ,它在支持从后面插入的同时支持从前端插入。而且它还重载了 operator [] 。

    ​ 它的初始化是和 vector 差不多的。

    ​ 它的单次操作复杂度也基本都是 (O(1))

    ​ 它 迭代器。

    ​ 下面默认定义 deque <int> Q

    8.1 begin

    8.2 clear

    8.3 empty

    8.4 end

    8.5 erase

    8.6 front

    Q.front() 会返回 Q 的第一个元素的引用。

    8.7 insert

    8.8 operator []

    Q[x] 返回 Q 从前往后数的第 x+1 个元素的引用。

    8.9 pop_back

    8.10 pop_front

    Q.pop_front() 表示弹出 Q 的第一个元素。

    8.11 push_back

    8.12 push_front

    Q.push_front(x) 表示在 Q 的最前面插入元素 x 。

    8.13 resize

    8.14 size

    8.15 relational operators

  • 相关阅读:
    UOJ 30 【CF Round #278】Tourists
    CodeForces 1070F Katya and Segments Sets
    Django系列3:Model的简单对接
    Django系列2:MTV简单流程
    python virtualenv
    vscode使用
    Django 系列1:Django简介
    vue-cli3/4 vue ui创建elementui项目
    npm安装参数
    vue系列11:vuex
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/STL.html
Copyright © 2011-2022 走看看