• 清北学堂2019.5.3


    Day 6(文泓宇【爱撒和zqf狗粮的 little sister】)

    今天讲的是有关OI中的STL库:

    首先,拒绝两个问题:
    这东西我自己也能写啊?
    这东西怎么写啊?

    STL:

    pair(自带排序【以第一关键字排序,以此类推】):

    algorithm库包括了utility库

    实例代码:

    #include <utility>
    using namespace std;
    pair<TypeName1, TypeName2> VariableName;
    pair<int, int> x;
    pair<double, double> y;
    pair<int, double> z;
    pair<pair<int, int>, int> a;

    1.作为需要返回多个量的函数返回值
    2.作为 struct 的替代
      Pair 的比较大小:先比较第一个元素,第一个元素相同时再比
    较第二个元素。
      如果两个元素都相等则判定相等。
    string(保证连续的2n的内存):

      作为字符串数组的替代:

    #include <string>
    using namespace std;
    string a;

    各种用法:

    a = b, a = ``Hello World'': 支持赋值
    a[i]: 支持下标访问
    a.size(): 字符串长度
    a + b: 支持字符串拼接
    a > b: 支持按字典序排序
    a.substr(x, y): x 位置开始,返回长度为 y 的子串

    vector:

    在空间需求很紧时不要用Vector

    引入:

    Problem 1
    有编号为 1 3000 × 3000 的人,每个人都属于一个队伍。一共有
    3000 个队伍,每个队伍 3000 人。如何存储这些数据?

    const int maxN = 3000;
    int team[maxN][maxN];

    Problem 2

    有编号为 1 3000 × 3000 的人,每个人都属于一个队伍。一共有
    3000 个队伍,每个队伍可能有任意多数人,也可能没有人。如何存
    储这些数据?

    const int maxN = 3000;
    const int maxM = 3000 * 3000;
    int team[maxN][maxM]; // Memory Limit Exceeded!

    不定长数组:不需要指定数组元素的数量,可以直接通过元素的个数分配内存:

    #include <vector>
    using namespace std;
    vector<TypeName> VariableName;
    vector<int> a;
    vector<double> b;
    vector<vector<int> > c;

    成员函数:

    a[0]: 随机下标访问, O(1).
    a.push_back(): 在末尾插入一个元素, O(1).
    a.pop_back(): 弹出末尾元, O(1).
    a.front(): 访问第一个元素(引用) , O(1).
    a.back(): 访问最后一个元素, O(1).
    a.clear(): 清空一个 Vector, O(n).
    a.empty(): 返回 Vector 是否为空, O(1).
    a.size(): 返回 Vector 中元素的个数, O(1).

    样例:接受 n 个整数的输入,倒序输出。

    #include <iostream>
    using namespace std;
    int main() {
    vector<int> a;
    int n, x;
    cin >> n;
    for (int i = 0; i < n; ++i) {
    cin >> x;
    a.push_back(x);
    }
    while (!a.empty()) {
    cout << a.back();
    a.pop_back();
    }
    return 0;
    }
    vector<int>::iterator it;

    迭代器 (iterator) 的作用类似于指针,是一个指明元素位置的量。什么类型的 Vector 就要用什么类型的迭代器。

    在迭代器前加一个*就可以对其进行求值。

    a.begin(): 返回第一个元素的迭代器
    a.end(): 返回最后一个元素的后一个迭代器
    *a.begin(): 等价于 a.front()
    *it: 得到 it 指向的值
    it++: 得到下一个位置的迭代器
    it += i: 得到下 i 个位置的迭代器, O(1)
    it1 - it2: 得到 it1 it2 之间的元素个数, O(1)

    vector<int>::iterator it;
    for (it = a.begin(); it != a.end(); ++it)
    {     cout
    << *it << endl; }

    C++11:
    auto(十分高端)【遍历vector】

    #include<vector>
    using namespace std;
    vector <int >a;
    int main()
    {
              for(auto x: a)
              {
               }          
    }

    set:

    集合:不能有重复元素 + 有序性

    #include <set>
    using namespace std;
    set<TypeName> VariableName;
    set<int> a;
    set<double> b;

    a.clear(): 清空元素
    a.empty(): 检查是否为空
    a.size(): 查看 set 内元素个数

    替罪羊,Splay,Treap等等······(树结构)

    Set 的底层使用红黑树这个数据结构来维护集合。

    a.begin(): 第一个元素的迭代器
    a.end(): 最后一个元素的后一个迭代器
    a.insert(): 插入一个元素, O(log n)
    a.erase(): 删除一个元素, O(log n)
    a.find(): 寻找一个元素, O(log n)
    a.count(): 查找某个元素的数量, O(log n)
    a.lower_bound(): 查找大于等于某个值的第一个元素, O(log n)
    a.upper_bound(): 查找大于某个值的第一个元素, O(log n)
    a.equal_range(): 查找等于某个值的左闭右开区间,返回一个pairO(log n)

    Erase一个不存在的数,将不会执行该语句

    具有鲁棒性

    #include <set>
    #include <iostream>
    using namespace std;
    int main() {
    set<int> a;
    a.insert(1); // a: {1}
    a.insert(1); // a: {1}
    a.insert(2); // a: {1, 2}
    a.remove(1); // a: {2}
    for (int i = 0; i < 5; ++i) {
    a.insert(i);
    } // a: {0, 1, 2, 3, 4}
    cout << a.size() << endl; // 5
    cout << a.count(4) << endl; // 1
    }

     Set 的迭代器和 Vector 的不同。

    set<int>::iterator it;

    *it: it 的求值
    ++it: it 的下一个迭代器
    --it: it 的前一个迭代器
    Vector: 随机访问迭代器
    Set: 双向迭代器

    重载运算符:

    struct Student {
    int grade;
    char name[20];
    }
    bool operator <(Student a, Student b) {
    return a.grade < b.grade;
    }

    或者也可以这么写:

    struct Student {
    int grade;
    char name[20];
    bool operator <(Student b) {
    return grade < b.grade;
    }
    }

    MultiSet :

    #include <set>
    using namespace std;
    multiset<TypeName> VariableName;
    multiset<int> s;

    multiset set 大部分操作相同,但支持在一个 set 内有多个元素。
    注意在 multiset 中,如果 erase 一个数,仍然会把全部的数字删除。

    map:

    Problem :

    给出许多学生的名字和成绩,要求使用名字找到成绩。
    比如学生 __debug 的微积分 59 分,我们希望能通过 __debug 找到 59.

    #include <map>
    using namespace std;
    map<TypeName1, TypeName2> VariableName;
    map<string, int> a;

    map 的本质就是一个元素为 pair set,重载了 [] 运算符。

    //这两行相同
    map<string,int>a;
    set<pair<string,int> >a;

    Stack (能不用就不用):

    一个先进后出的结构【FILO】

    #include <stack>
    using namespace std;
    stack<TypeName> VariableName;
    stack<int> a;

    其成员函数为:

    a.size()
    a.empty()
    a.top(): 访问栈顶元素
    a.pop(): 弹出栈顶
    a.push(): 压入一个元素

    Queue(这个好像十分的实用):

    一个先进先出的结构【FIFO】

    #include <queue>
    using namespace std;
    queue<TypeName> VariableName;
    queue<int> a;

    其成员函数有:

    a.size()
    a.empty()
    a.front(): 访问队首元素
    a.pop(): 弹出队首
    a.push(): 在队末尾加入一个元素

    Priority Queue(优先队列):

    一个类似于队列的结构,与其不同的是:队列每次出最先进队的元素,而优先队列每次出的是最大的元素。

    与set相类似,需要重载<运算符

    #include<queue>
    using namespace std;
    priority_queue<TypeName> VariableName;
    priority_queue<int> a; 

    其成员函数有:

    a.size()
    a.empty()
    a.top(): 访问堆顶
    a.pop(): 弹出堆顶
    a.push(): 向堆中加入一个元素

    Algorithm库

    Sort:

    是对于一个数列进行排序(默认从小到大)【若想要其他排列可以自己写了之后加入sort当中】

    例如:

    sort(a+1,a+n+1,cmp);

    这里的cmp就需要自己去写

    #include <algorithm>
    using namespace std;
    int a[30];
    vector<int> b;
    int main() {
    sort(a, a + 30);
    sort(b.begin(), b.end());
    }

    Reverse:

    就是个反的sort

    #include <algorithm>
    using namespace std;
    int a[30];
    vector<int> b;
    int main() {
      reverse(a, a + 30);
      reverse(b.begin(), b.end());
    }

    Unique(去重)【必须作用在有序的上】

    将多余的全部清零的步骤:

    fill(unique(a,a+10),a+10,0);

    区分:

      Fill是赋值

      Memset是清空

    Next Permutation:

    要求数组中元素可以比较。
    均摊复杂度 O(1),单次运算交换次数不超过
    distance(AiAi+1)/2Ai; Ai+1 分别为第 i, i + 1 个排列。

    int a[] = {1, 2, 3, 4};
    do {
    ...
    } while (!next_permutation(a, a + 5));

    再往后的就是一些神奇的东西了(我听的一懵一懵的TAT)

    Binary Search 【有一点像二分查找】(要求有序):

    #include <iostream>
    #include <algorithm>
    #include <vector>
    int main()
    {
      std::vector<int> a {1, 3, 4, 5, 9};
      std::vector<int> b {1, 2, 3};
      for (auto x : b) {
        if (std::binary_search(a.begin(), a.end(), x)) {
          std::cout << "Found " << needle << '
    ';
        }  
        
    else {       std::cout << "no dice! ";     }   } }

    Nth Element :

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <functional>
    int main()
    {
      std::vector<int> v{5, 6, 4, 3, 2, 6, 7, 9, 3};
      std::nth_element(v.begin(), v.begin() + v.size()/2, v.end());
      std::cout << "The median is " << v[v.size()/2] << '
    ';
      std::nth_element(v.begin(), v.begin()+1, v.end(), std::greater<int>());
      std::cout << "The second largest element is " << v[1] << '
    ';
    }

    Random Shufe

    #include <random>
    #include <algorithm>
    #include <iterator>
    #include <iostream>
    int main()
    {
      std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
      std::shuffle(v.begin(), v.end(), g);
    }
  • 相关阅读:
    web.xml配置文件
    数组去重问题
    Mysql优化
    点赞功能
    IDEA的一些使用小技巧
    Maven
    AJAX
    HTTP响应头拆分/CRLF注入详解
    对寄存器ESP和EBP的一些理解
    汇编调用指令的执行过程
  • 原文地址:https://www.cnblogs.com/gongcheng456/p/10805028.html
Copyright © 2020-2023  润新知