C++

重学C++系列(十)C++高级编程

Posted by YaPi on January 28, 2022

STL

Standard Template Library

  • STL算法是泛型的(generic),不与任何特定数据结构和对象绑定,不必在环境类似的情况下重写代码
  • STL算法可以量身定做,并且具有很高的效率
  • STL可以进行扩充,可以编写自己的组建并且能与STL标准的组建进行很好的配合

avatar

容器

STL的容器分为两大类: 序列式容器:其中的元素都是可排序的,STL提供了vector、list、deque等序列式容器。 stack、queue、priority_queue是容器适配器,即是说它们是根据deque进行修改产生的。

关联式容器: 每个元素都是由一个键、一个值组成。常见的关联容器如:set、multiset、map、multimap set中key、value唯一,若想重复需使用multiset。

序列容器
#include <iostream>
#include "vector"
#include "list"
#include "queue"
#include "stack"
using namespace std;
struct Display{
    void operator()(int i){
        cout << i << " ";
    }
};

int main() {
    int iArr[] = {1,2,3,4,5};
    vector<int> iVector(iArr,iArr + 4);
    list<int> iList(iArr,iArr + 4);
    deque<int> iDeque(iArr,iArr + 4);

    for_each(iVector.begin(),iVector.end(),Display());
    cout<< endl;
    for_each(iList.begin(),iList.end(),Display());
    cout<< endl;
    for_each(iDeque.begin(),iDeque.end(),Display());

    // 队列 先进显出
    queue<int> iQueue(iDeque);
    // 栈 先进后出
    stack<int> iStack(iDeque);
    // 优先队列,按优先权
    priority_queue<int> iPQueue(iArr,iArr + 4);
    cout<< endl;
    while(!iQueue.empty()){
        cout << "iQueue " << iQueue.front() << " ";
        // 出队
        iQueue.pop();
    }
    cout<< endl;
    while(!iPQueue.empty()){
        // 栈顶
        cout << "iPQueue " << iPQueue.top() << " ";
        // 出队
        iPQueue.pop();
    }
    cout<< endl;
    while(!iStack.empty()){
        // 栈顶
        cout << "iStack " << iStack.top() << " ";
        // 出队
        iStack.pop();
    }
    return 0; // text 代码区
}
关联式容器
#include <iostream>
#include "map"
using namespace std;
struct Display{
    void operator()(pair<string,double> info){
        cout << info.first << " "<< info.second << endl;
    }
};

int main() {
    map<string,double> studentScore;
    studentScore["LiMing"] = 95.0;
    studentScore["LiHong"] = 89.5;
    // map 中key的值是唯一的 若有值是修改
    studentScore["LiHong"] = 99.5;

    studentScore.insert(pair<string,double>("zhang",100));
    studentScore.insert(map<string,double>::value_type("wang",94.5));

    for_each(studentScore.begin(),studentScore.end(),Display());
    cout<< endl;

    map<string,double>::iterator  iter;
    iter = studentScore.find("zhang");
    // 找得到就返回,找不到iter就会遍历到尾部
    if (iter != studentScore.end()){
        cout << "Fount the score is : " << iter ->second << endl;
    }else {
        cout << "Not find" << endl;
    }
    iter = studentScore.begin();
    // 迭代器遍历删除问题:不能直接删除
    while(iter != studentScore.end()){
        if (iter->second < 95.0){
            // 去除不是小于95.0的元素
            // 这里不应该是iter,而应该是iter++
            studentScore.erase(iter++);
        }else {
            iter ++;
        }
    }
    cout << endl;
    for_each(studentScore.begin(),studentScore.end(),Display());

    // 迭代器遍历删除问题:不能直接删除
    for(iter = studentScore.begin();iter != studentScore.end();iter ++){
        if (iter ->second < 95){
            // 直接删除当前结果是错误的
            //studentScore.erase(iter);

            // erase删除一个迭代器会返回一个新的迭代器
            iter = studentScore.erase(iter);
        }
    }
    for_each(studentScore.begin(),studentScore.end(),Display());

    // 通过find得到并删除元素
    iter = studentScore.find("zhang");
    studentScore.erase(iter);

    for_each(studentScore.begin(),studentScore.end(),Display());


    // 删除指定元素
    int n = studentScore.erase("zhang");
    cout << n << endl;
    for_each(studentScore.begin(),studentScore.end(),Display());

    // 删除所有元素
    studentScore.erase(studentScore.begin(),studentScore.end());
    for_each(studentScore.begin(),studentScore.end(),Display());

    return 0;
}

仿函数

仿函数一般不会单独使用,主要是为了搭配STL算法使用。

本质就是类重载类一个operator(),创建一个行为类似函数的对象。

#include <iostream>
#include "algorithm"
using namespace std;
template<class T>
inline void Display(T const &a){
    cout << a << " " <<endl;
};
template<class T>
bool MySort(T const &a, T const &b){
    return a > b;
};


template<class T>
struct SortF{
    inline bool operator()(T const &a ,T const &b)const{
        return a > b;
    }
};

template<class T>struct DisplayF{
    inline void operator()(T const &a)const{
        cout << a << " ";
    }
};

int main() {
    int arr[] = {4,3,2,1,7};
    sort(arr,arr+5, MySort<int>);
    for_each(arr,arr+5,Display<int>);

    // C++放函数模版
    int arr2[] = {4,3,2,1,77};
    sort(arr2,arr2+5, SortF<int>());
    for_each(arr2,arr2+5,DisplayF<int>());

    return 0;
}

算法 algorithm

STL中算法大致分为四类

  1. 非可变序列算法:指不可以修改它们所操作的容器内容的算法
  2. 可变序列算法:指可以修改它们所操作的容器内容的算法
  3. 排序算法:包括对序列进行排序和合并的算法、搜索算法、及有序序列上的集合操作
  4. 数值算法:对容器内容进行数值计算

主要在algorithm、functional、numeric包中

#include <iostream>
#include "algorithm"
#include "functional"
using namespace std;

int main() {
    int arr[] = {1,2,3,4,5};
    int arr2[] = {10,20,30,40,50};
    int results[5];
    transform(arr,arr+5,arr2,results,std::plus<int>());
    // lambda 表达式 [外部传入参数](使用参数) -> void {}
    for_each(results,results+5,[](int a){ cout << a <<" ";});

    return 0;
}