05_泛型编程与STL之黑马程序员day05

拈花ヽ惹草 提交于 2020-03-10 14:01:24

#2020/03/10
day01至day05完结

1.map容器

此处不再对函数具体介绍,可进入Cpp参考

#include <iostream>
#include <map>
using namespace std;

//map容器初始化
void test01(){
    //map容器模板参数,第一个参数key的类型,第二参数value类型
    map<int, int> mymap;
 
    //插入数据  pair.first key值 piar.second value值
    //第一种
    pair<map<int, int>::iterator, bool> ret = mymap.insert(pair<int, int>(10, 10));           
    //iterator表示插入的位置
    if (ret.second){
        cout << "第一次插入成功!" << endl;
    }
    else{
        cout << "插入失败!" << endl;
    }
    ret = mymap.insert(pair<int, int>(10, 20));
    if (ret.second){
        cout << "第二次插入成功!" << endl;
    }
    else{
        cout << "插入失败!" << endl;
    }
    //第二种
    mymap.insert(make_pair(20, 20));
    //第三种
    mymap.insert(map<int, int>::value_type(30,30));
    //第四种
    mymap[40] = 40;
    mymap[10] = 20; 
    mymap[50] = 50;
    //发现如果key不存在,创建pair插入到map容器中
    //如果发现key存在,那么会修改key对应的value

    //打印
    for (map<int, int>::iterator it = mymap.begin(); it != mymap.end();it ++){
        // *it 取出来的是一个pair
        cout << "key:" << (*it).first << " value:" << it->second << endl;
    }
    
    //如果通过[]方式去访问map中一个不存在key,
    //那么map会将这个访问的key插入到map中,并且给value一个默认值
    cout << " mymap[60]: " <<  mymap[60] << endl;

    //打印
    for (map<int, int>::iterator it = mymap.begin(); it != mymap.end(); it++){
        // *it 取出来的是一个pair
        cout << "key:" << (*it).first << " value:" << it->second << endl;
    }
}

class MyKey{
public:
    MyKey(int index,int id){
        this->mIndex = index;
        this->mID = id;
    }
public:
    int mIndex;
    int mID;
};

struct mycompare{
    bool operator()(MyKey key1, MyKey key2){
        return key1.mIndex > key2.mIndex;
    }
};

void test02(){
    map<MyKey, int, mycompare> mymap; //自动排序,自定数据类型,咋排?
    
    mymap.insert(make_pair(MyKey(1, 2), 10));
    mymap.insert(make_pair(MyKey(4, 5), 20));

    for (map<MyKey, int, mycompare>::iterator it = mymap.begin(); it != mymap.end();it ++){
        cout << it->first.mIndex << ":" << it->first.mID << " = " << it->second << endl;
    }
}

//equal_range
void test03(){
    map<int, int> mymap;
    mymap.insert(make_pair(1, 4));
    mymap.insert(make_pair(2, 5));
    mymap.insert(make_pair(3, 6));

    pair<map<int, int>::iterator, map<int, int>::iterator> ret =  mymap.equal_range(2);
    if (ret.first != mymap.end()){
        cout << "找到lower_bound!" << endl;
    }
    else{
        cout << "没有找到";
    }

    if (ret.second != mymap.end()){
        cout << "找到upper_bound!" << endl;
    }
    else{
        cout << "没有找到";
    }
}

int main(void){
    //test01();
    //test02();
    test03();

    return 0;
}

2.multimap容器

multimap案例_员工分组

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <time.h>
#include <stdlib.h>
using namespace std;

#define SALE_DEPATMENT 1 //销售部门
#define DEVELOP_DEPATMENT 2 //研发部门
#define FINACIAL_DEPATMENT 3 //财务部门

//multimap 案例
//公司今天招聘了 5 个员工, 5 名员工进入公司之后,需要指派员工在那个部门工作
//人员信息有: 姓名 年龄 电话 工资等组成
//通过 Multimap 进行信息的插入 保存 显示
//分部门显示员工信息 显示全部员工信息

class Worker{
public:
    string mName;
    string mTele;
    int mAge;
    int mSalary;
};

void Create_Worker(vector<Worker>& vWorker){
    string seedName = "ABCDE";
    for (int i = 0; i < 5;i ++){
        Worker worker;
        worker.mName = "员工";
        worker.mName += seedName[i];

        worker.mAge = rand() % 10 + 20;
        worker.mTele = "010-8888888";
        worker.mSalary = rand() % 10000 + 10000;
        //保存员工信息
        vWorker.push_back(worker);
    }
}

//员工分组
void WorkerByGroup(vector<Worker>& vWorker, multimap<int, Worker>& workerGroup){
    //把员工随机分配不同部门
    srand(time(NULL));
    for (vector<Worker>::iterator it = vWorker.begin(); it != vWorker.end();it ++){
        int departID = rand() % 3 + 1;
        switch (departID){
            case SALE_DEPATMENT:
                 workerGroup.insert(make_pair(SALE_DEPATMENT,*it));
                 break;
            case DEVELOP_DEPATMENT:
                 workerGroup.insert(make_pair(DEVELOP_DEPATMENT, *it));
                 break;
            case FINACIAL_DEPATMENT:
                 workerGroup.insert(make_pair(FINACIAL_DEPATMENT, *it));
                 break;
            default:
                 break;
        }
    }
}

void ShowGroupWorkers(multimap<int, Worker>& workerGroup, int departID){
    multimap<int, Worker>::iterator it = workerGroup.find(departID);
    //找当前部门总人数
    int DepartCount = workerGroup.count(departID);
    int num = 0;
    for (multimap<int, Worker>::iterator pos = it; it != workerGroup.end() && num <     
    DepartCount; pos++, num++){
        cout << "姓名:" << pos->second.mName << " 年龄:" << pos->second.mAge << " 电话:" <<    
        pos->second.mTele << " 工资:" << pos->second.mSalary << endl;
     }
}

//打印每一部分员工信息
void PrintWorkerByGroup(multimap<int, Worker>& workerGroup){
    //打印销售部员工信息

    //显示销售部门
    cout << "销售部门:" << endl;
    ShowGroupWorkers(workerGroup,SALE_DEPATMENT);
    //显示开发部门
    cout << "研发部门:" << endl;
    ShowGroupWorkers(workerGroup, DEVELOP_DEPATMENT);
    //显示财务部门
    cout << "财务部门:" << endl;
    ShowGroupWorkers(workerGroup, FINACIAL_DEPATMENT);
}

int main(void){
    //存放新员工的信息
    vector<Worker> vWorker;
    //multimap保存分组信息
    multimap<int, Worker> workerGroup;
    //创建员工
    Create_Worker(vWorker);
    //员工分组
    WorkerByGroup(vWorker, workerGroup);
    //打印每一部分员工信息
    PrintWorkerByGroup(workerGroup);

    return  0;
}

3.容器深拷贝和浅拷贝

深拷贝和浅拷贝的区别如下图所示:
在这里插入图片描述

#include <iostream>
#include <vector>
using namespace std;

class Person{
public:
    Person(char* name,int age){
        this->pName = new char[strlen(name) + 1];
        strcpy(this->pName, name);
        this->mAge = age;
    }
    Person(const Person& p){
        this->pName = new char[strlen(p.pName) + 1];
        strcpy(this->pName, p.pName);
        this->mAge = p.mAge;
    }
    Person& operator=(const Person& p){  // 该重载函数用于解决浅拷贝问题
        if (this->pName != NULL){
            delete[] this->pName;
        }
        this->pName = new char[strlen(p.pName) + 1];
        strcpy(this->pName, p.pName);
        this->mAge = p.mAge;

        return *this;
    }
    ~Person(){
        if (this->pName != NULL){
            delete[] this->pName;
         }
    }
public:
    char* pName; //指针 容易浅拷贝的问题
    int mAge;
};

void test01(){
    Person p("aaa",20);
    vector<Person> vPerson;
    vPerson.push_back(p);  //实际上p被拷贝进vector容器之中,浅复制会导致一次构造、两次析构
}

int main(void){
    test01();

    return 0;
}

4.函数对象

具体用法看test01()中的注释及下方代码示例:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct MyPrint{   //函数对象(仿函数)
    MyPrint(){
        mNum = 0;
    }
    void operator()(int val){
        mNum++;
        cout << val << endl;
    }
public:
    int mNum;
};

int num = 0; //真正开发中,尽量避免去使用全局变量 加锁解锁
void MyPrint02(int val){
    num++;
    cout << val << endl;
}

void test01(){
    MyPrint print;
    print(10);
 
    //函数对象可以像普通函数一样调用
    //函数对象可以像普通函数那样接收参数
    //函数对象超出了函数的概念,函数对象可以保存函数调用的状态
}

void test02(){
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);

    //计算函数调用次数
#if 0
    MyPrint02(10);
    MyPrint02(20);
    cout << num << endl;
    
    MyPrint print;
    print(10);
    print(20);
    cout << print.mNum << endl;
#endif

    MyPrint print;
    MyPrint& print02 = for_each(v.begin(), v.end(), print);  // 原理可参考for_each()的定义

    cout << "print调用次数:" << print.mNum << endl;
    cout << "print调用次数:" << print02.mNum << endl;  //显示真正的调用次数
}

int main(void){
    test02();
    
    return 0;
}

5.内建函数对象

内建函数不需要自己定义,可以直接新建函数对象

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

void test01(){
    plus<int> myplus;
    cout << myplus(10, 20) << endl;
}

int main(void){
    test01();
    
    return 0;
}

6.函数对象适配器

具体见代码注释

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

//如果要适配,一定要继承binary_function<...>
struct MyPrint : public binary_function<int,int,void> {
// binary_function<int, int, void>中的void与operator()的返回类型相同
 // <int, int, void>的int, int与operator()(int, int)相同
    void operator()(int v,int val) const{
        cout << "v:" << v << " val:" << val << endl;
        cout << v + val << " ";
    }
};

//仿函数适配器 bind1st bind2nd 绑定适配器
void test01(){
    vector<int> v;
    for (int i = 0; i < 10;i ++){
        v.push_back(i);
    }
   
    int addNum = 200;
    for_each(v.begin(), v.end(), bind1st(MyPrint(), addNum));
    //绑定适配器  将一个二元函数对象转变成一元函数对象
    //bind1st bind2nd区别?
    //bind1st,将addNum绑定为函数对象的第一个参数
    //bind2nd,将addNum绑定为函数对象的第二个参数
}

struct MyPrint02{
    void operator()(int v){
        cout << v << " ";
    }
};

struct MyCompare : public binary_function<int,int,bool>{
    bool operator()(int v1, int v2) const{
        return v1 > v2;
    }
};

struct MyGreater5 : public binary_function<int,int,bool>{  //operator()(int)用unary_function<int, bool>
    bool operator()(int v,int val) const{
    cout << "v:" << v << " val:" << val << endl;
    return v < val;
    }
};

//仿函数适配器 not1 not2 取反适配器
void test02(){
    vector<int> v;
    for (int i = 0; i < 10; i++){
        v.push_back(i);
    }
    
    for_each(v.begin(), v.end(), MyPrint02()); cout << endl;
    sort(v.begin(), v.end(), not2(MyCompare()));
    for_each(v.begin(), v.end(), MyPrint02()); cout << endl;

    //not1 not2 
    //如果对二元谓词取反,用not2
    //如果对一元谓词取反,用not1
    vector<int>::iterator it = find_if(v.begin(), v.end(),not1(bind2nd(MyGreater5(),5)));
    if (it == v.end()){
        cout << "没有找到" << endl;
    }
    else{
        cout << *it << endl;
    }
}

//仿函数适配器 ptr_fun
void MyPrint03(int val,int val2){
    cout << "val1:" << val << " val2:" << val2 << endl;
    cout << val + val2 << endl;
}

void test03(){
    vector<int> v;
    for (int i = 0; i < 10; i++){
        v.push_back(i);
    }
    //ptr_func把普通函数 转成  函数对象
    for_each(v.begin(), v.end(), bind2nd(ptr_fun(MyPrint03),10));
}

//成员函数适配器 mem_fun mem_fun_ref
class Person{
public:
    Person(int age, int id) :age(age), id(id){}
    void show(){
        cout << "age:" << age << " id:" << id << " aaa" << endl;
    }
public:
    int age; 
    int id;
};
void test04(){
    //如果容器中存放的对象或者对象指针,我们for_each算法打印的时候,调用类
    //自己提供的打印函数,for_each()既可以接受普通函数也可以接受函数对象

    vector<Person> v;
    Person p1(10, 20), p2(30, 40), p3(50, 60);
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);

    //格式: &类名::函数名
    for_each(v.begin(), v.end(), mem_fun_ref(&Person::show));

    vector<Person*> v1;
    v1.push_back(&p1);
    v1.push_back(&p2);
    v1.push_back(&p3);

    for_each(v1.begin(),v1.end(),mem_fun(&Person::show));

    //mem_fun_ref mem_fun区别?
    //如果存放的是对象指针 使用mem_fun
    //如果使用的是对象 使用mem_fun_ref
}

int main(void){
    //test01();
    //test02();
    //test03();
    test04();
    
    return 0;
}

7.常用的遍历算法

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

//transform 将一个容器的元素 搬运 到另一个容器中
struct MyPlus{
    int operator()(int val){
        return val + 100;
    }
};

void MyPrint(int val){
    cout << val << " ";
}
void test01(){
    vector<int> v1;
    vector<int> v2;

    for (int i = 0; i < 10;i++){
        v1.push_back(i);
    }

    v2.resize(v1.size()); //开辟空间

    //v1.begin()到v1.end()的值依次传给MyPlus(),MyPlus的返回值再传给v2
    transform(v1.begin(), v1.end(), v2.begin(), MyPlus());  
    for_each(v2.begin(), v2.end(), MyPrint);
    cout << endl;
}

//常用的查找算法
void test02(){
    vector<int> v1;
    for (int i = 0; i < 10; i++){
        v1.push_back(i);
    }
    
    vector<int>::iterator ret = find(v1.begin(), v1.end(), 5);
    if (ret == v1.end()){
        cout << "么有找到!" << endl;
    }
    else{
        cout << "找到了:" << *ret << endl;
    }
}

class Person{
public:
    Person(int age, int id) :age(age), id(id){}
    bool operator==(const Person& p) const{
        return p.id == this->id && p.age == this->age;
    }
public:
    int id;
    int age;
};

void test03(){
    vector<Person> v1;
    
    Person p1(10, 20), p2(20, 30);

    v1.push_back(p1);
    v1.push_back(p2);

    vector<Person>::iterator ret =  find(v1.begin(), v1.end(), p1);
    if (ret == v1.end()){
        cout << "么有找到!" << endl;
    }
    else{
        cout << "找到了:" << endl;
    }
}

//binary_search 二分查找法
bool MySearch(int val){
    return val > 5;
}
bool MySearch2(int val){
    return val > 5;
}
void test04(){
    vector<int> v1;
    for (int i = 0; i < 10; i++){
        v1.push_back(i);
    }
    v1.push_back(9);

    bool ret =binary_search(v1.begin(), v1.end(), 5);
    if (ret){
        cout << "找到!" << endl;
    }else{
        cout << "没有找到!" << endl;
    }

    vector<int>::iterator it =  adjacent_find(v1.begin(), v1.end());
    if (it != v1.end()){
        cout << "找到相邻重复元素:" << *it <<  endl;
    }
    else{
        cout << "没有找打相邻重复元素" << endl;
    }

    //find_if 会根据我们的条件(函数) ,返回第一个满足条件的元素的迭代器
    it =  find_if(v1.begin(), v1.end(), MySearch);
    if (it != v1.end()){
        cout << "找到:" << *it << endl;
    }
    else{
        cout << "没有找到" << endl;
    }
    
    //count count_if
    int num = count(v1.begin(), v1.end(), 9);
    cout << "9出现的次数:" << num << endl;
    num = count_if(v1.begin(), v1.end(), MySearch2);
    cout << "大于5的个数:" << num << endl;
}

int main(void){
    //test01();
    //test02();
    //test03();
    test04();

    return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!