栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

学习C++:C++进阶(一)标准模板库STL

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

学习C++:C++进阶(一)标准模板库STL

目录

1.STL简介及一个例子

1.0 STL基本概念

1.1 STL初识

1.1.1 原生指针与vector

1.1.2 自定义数据类型如何用迭代器迭代

2.容器

2.1 string容器

2.1.1 string容器基本概念

2.1.2  string构造函数

2.1.3  string赋值操作

2.1.4  string的存取操作

2.1.5  string的拼加操作 

2.1.6 string的查找操作

2.1.7 string的比较操作  

2.1.8 子串

2.1.9 案例:解析字符串

2.1.10  string插入和删除操作

2.1.11  string与c语言风格的代码转换

2.2 vector容器

2.2.1 vector容器的空间扩展机制

2.2.2 vector构造函数

2.2.3 vector赋值函数

2.2.4 vector本身属性有关函数

2.2.5 vector数据存取遍历操作

2.2.6 插入和删除

2.2.7 案例1:巧用swap收缩内存

2.2.8 案例2:巧用reserve预留空间

2.3 deque容器

2.3.1 deque容器简介

2.3.2 构造函数

2.3.3 deque赋值函数

2.3.4 vector本身属性有关函数

2.3.5 vector数据存取遍历操作

2.3.6 插入和删除

2.3.7 案例:利用容器实现评委打分

2.4 stack栈容器

2.4.1 stack容器基本概念

2.4.2 栈的构造函数

2.4.3 栈的其余接口

2.5 queue队列容器

2.5.1 queue容器基本简介

2.5.2 队列的一些接口

2.6 list容器

2.6.1 list简介

2.6.2 list的迭代器

2.6.3 list构造函数

2.6.4 list元素插入和删除操作

  ​编辑

2.6.5 list大小、赋值、数据存取操作

2.7 set容器

2.7.1 set容器基本概念

2.7.2 set容器常用API

2.7.3 pair对组的创建

2.7.4 一些问题

2.8 map容器

2.8.1 基本概念

2.8.2 常用API

2.9 STL容器使用时机

3 常用算法

3.1 函数对象

3.1.1 函数对象

3.1.2 谓词

3.1.3 内建函数对象

3.1.4 适配器

3.2 常用算法介绍

3.2.1 常用遍历算法

3.2.2 常用查找算法

3.2.3 常用排序算法

3.2.4 常用拷贝和替换算法

3.2.5 常用算术生成算法

3.2.6 常用集合算法


1.STL简介及一个例子

1.0 STL基本概念

1.STL概念

        STL(Stardard Template Libiary)模板标准库

        STL从广义上分为:容器、算法、迭代器,容器和算法之间通过迭代器进行无缝连接。STL几乎所有的代码都采用了模板类或模板函数,这相比传统的由函数和类组成的库来说提供了更好的代码重用机会。

2.STL六大组件简介

容器:各种数据结构,如vector、list、deque、set、map用来存放数据,从实现的角度来说,STL容器是一种class template

算法:各种常用的算法,如sort、find、copy、for_each, 从实现的角度来说,STL算法是一种function template

迭代器:扮演了容器与算法之间的胶合剂,共有五种类型,从实现来看,迭代器是一种将operator*,operator->,operator++,operator--,operator*等指针相关操作予以重载的class template。所有stl容器都附带自己专属的迭代器,只有容器的设计者才可能指导如何遍历自己的元素。原生指针是一种迭代器。

仿函数:行为类似函数,可作为算法的某种策略。从实现角度看,仿函数是一种重载了operator()的class或者class template

适配器:一种用来修饰容器或者仿函数或迭代器接口的东西。

空间适配器:负责空间的配置与管理。从实现角度看,配置器是一个实现了动态空间配置,空间管理、空间释放的class template

 3.STL六大组件相互关系

容器通过空间配置器取得存储空间,算法通过迭代器存储容器中的内容,仿函数可以协助算法完成不同策略的变化,适配器可以修饰仿函数。

1.1 STL初识

1.1.1 原生指针与vector

1.原生指针遍历数组元素

void test01()
{
    int arr[5] = {1,2,3,4,5};
    int * p = arr;
    for(int i=0 ; i<5 ; i++)
    {
        cout << *(p++) << " " ;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
Hello, World!

2.利用vector容器与迭代器遍历数组元素

Ⅰ.第一种使用方式

void test02()
{
    vectorv;                                   //创建一个vector容器,容器中存放的数据类型是int类型
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);

    vector::iterator itBegin = v.begin();      //起始迭代器,指向容器中第一个元素
    vector::iterator itEnd = v.end();          //结束迭代器,指向容器中最后一个元素的下一个位置
    while (itBegin!=itEnd)
    {
        cout << *itBegin << " " ;
        itBegin++;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
10 20 30 40 

Ⅱ.第二种使用方式

void test03()
{
    vectorv;                                   //创建一个vector容器,容器中存放的数据类型是int类型
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);

    for(vector::iterator it = v.begin() ; it!=v.end();it++)
    {
        cout << *it << " " ;
    }
}

Ⅲ.foreach遍历,需要包含头文件algorithm

void myprint(int val)
{
    cout << val << " " << endl;
}

void test04()
{
    vectorv;                                   //创建一个vector容器,容器中存放的数据类型是int类型
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);

    for_each(v.begin(),v.end(), myprint);
}

解释一下代码:第一个参数为起始;第二个参数为终点;第三个参数叫做回调函数;在执行时,判断起始是否==终点,若不等于则继续运行,将v.begin()指针所指的数据(本例为int)传给回调函数(myprint)执行。

1.1.2 自定义数据类型如何用迭代器迭代

1.code

void test05()
{
    vectorv;
    Person p1("aaa",10);
    Person p2("bbb",20);
    Person p3("ccc",30);
    Person p4("ddd",40);
    Person p5("eee",50);
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);
    v.push_back(p4);
    v.push_back(p5);
    for(vector::iterator it = v.begin() ; it!=v.end() ;it++)
    {
        cout  << "name is :" << (*it).name << endl;
        cout << "age is :" << it->age << endl;
    }
}

2.代码解释

在for循环中需要解引用,那么*it是什么呢,其实就算容器的内容。

3. 自定义类型中放指针:深入理解*it

void test05()
{
    vectorv;
    Person p1("aaa",10);
    Person p2("bbb",20);
    Person p3("ccc",30);
    Person p4("ddd",40);
    Person p5("eee",50);
    v.push_back(&p1);
    v.push_back(&p2);
    v.push_back(&p3);
    v.push_back(&p4);
    v.push_back(&p5);
    for(vector::iterator it = v.begin() ; it!=v.end() ;it++)
    {
        //*it == Person*
        cout  << "name is :" << (*(*it)).name << endl;
        cout << "age is :" << (*it)->age << endl;
    }
}

4.容器的嵌套

void test06()
{
    vector>v;

    vectorv1;
    vectorv2;
    vectorv3;

    for(int i=0 ; i<5 ; i++)
    {
        v1.push_back(i+1);
        v2.push_back(i+10);
        v3.push_back(i+100);
    }

    v.push_back(v1);
    v.push_back(v2);
    v.push_back(v3);

    for(vector>::iterator it = v.begin();it!=v.end();it++)
    {
        // *it  是 vector
        for(vector::iterator vit = (*it).begin() ;vit!=(*it).end();vit++)
        {
            cout << *vit << " " ;
        }
        cout << endl;
    }

}

代码解释:一个大容器,三个小容器;三个小容器装有五个数据。第一个for循环没有什么问题,它会遍历三次。遍历类型为vector类型数据,第二个for循环遍历int型数据,五次。

*it表示的是当前容器,看看是否到结束位置。

2.容器

2.1 string容器

2.1.1 string容器基本概念

1.char * 与 string 区别

Ⅰ.char * 是一个指针,string是一个类

string封装了char *,管理这个字符串,是一个char *的容器

Ⅱ.string封装了许多实用的成员方法

查找find,拷贝copy,删除delete,替换replace,插入insert

Ⅲ.不用考虑内存释放和越界

string管理char *所分配的内存。每一次string的复制,取值都由string类负责维护,不用担心复制越界

2.1.2  string构造函数

1.默认构造:string()

创建一个空的字符串,比如string str;

2.拷贝构造:string(const string & str)

使用一个string对象初始化一个string对象

3.有参构造:string(const char * s) 使用字符串s初始化

void test07()
{
    char * string1 = "shabi";
    string string2(string1);
    cout << "string 2 is :" << string2 << endl;
}

4.有参构造:string(int n,char c) 使用n个字符c初始化

void test08()
{
    string string1(10,'a');
    cout << string1 << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
aaaaaaaaaa

2.1.3  string赋值操作

1.string& operator=(const char * s):char*类型字符串赋值给当前字符串

void test08()
{
    string string1;
    string1 = "sb" ;
}

2. string& operator=(const string &s):把字符串s赋值给当前的字符串

void test08()
{
    string string1;
    string string2;
    string1 = "sb" ;
    string2 = string1;
}

3. string& operator=(char c):字符赋值给当前字符串

4.string& assign(const char * s):把字符串s赋值给当前的字符串

void test08()
{
    string string1;
    string1.assign("aba");
    cout << "string1 = " << string1 << endl;
}

5. string& assign(const char * s,int n):把字符串s的前n个字符赋值给当前的字符串

void test08()
{
    string string1;
    string1.assign("abajsjdaa",4);
    cout << "string1 = " << string1 << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
string1 = abaj

6. string& assign(const string& s,int n):把字符串s赋值给当前的字符串

7.string& assign(int n,char c):用n个字符c赋值给当前字符串

8.string& assign(const string & s, int start ,int n):start开始的n个字符赋值给字符串

void test08()
{
    string string1;
    string1.assign("abajsjdaa",4,2);
    cout << "string1 = " << string1 << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
string1 = sj

2.1.4  string的存取操作

1.string的获取长度的接口

str.size()

2.string类型数据的随机读取(1)----[]

void test08()
{
    string string1 = "hello world";
    for(int i=0;i 
 
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
h
e
l
l
o
 
w
o
r
l
d

3.string类型数据的随机读取(2)----str.at(i)

void test08()
{
    string string1 = "hello world";
    for(int i=0;i 

4.[]与at(i)的区别

[]访问异常直接挂掉,而at访问异常,抛出out_of_range异常

void test08()
{
    string string1 = "hello world";
    try
    {
        cout << string1.at(100);
    }
    catch (out_of_range e)
    {
        cout << "exception" << e.what() << endl;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
exceptionbasic_string::at: __n (which is 100) >= this->size() (which is 11)

2.1.5  string的拼加操作 

1.+=

void test09()
{
    string s1 = "I";
    string s2 = " love you";
    s1 += s2;
    cout << s1 << endl;
}

2.append(string)函数

void test09()
{
    string s1 = "I";
    string s2 = " love you";
    s1.append(s2);
    cout << s1 << endl;
}

2.1.6 string的查找操作

1.int find(const string & str/char*,int pos = 0)const; :查找str第一次出现的位置,从pos开始查找

void test09()
{
    string s1 = "abcdefghi" ;
    cout << "position is: " << s1.find("de") << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
position is: 3

进程已结束,退出代码0

若返回-1代表查找失败。

ps:rfind是从右往左查询

2.string& repalce(int pos,int n,const string & str):替换从pos开始n个字符为字符串str

void test09()
{
    string s1 = "abcdefghi" ;
    s1.replace(1,3,"111");
    cout << s1 << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
a111efghi

2.1.7 string的比较操作  

1.compare

void test10()
{
    string str1 = "hello";
    string str2 = "hello";
    if(str1.compare(str2) == 0)
    {
        cout << "str1 == str2" << endl;
    }
    else if(str1.compare(str2) > 0)
    {
        cout << "str1 > str2" << endl;
    }
    else
    {
        cout << "str1 < str2" << endl;
    }
}

2.1.8 子串

1.string substr(int pos = 0,int n = pos)const; :返回由pos开始的n个字符组成的字符串

void test11()
{
    string string1 = "abcdef";
    string subStr =string1.substr(0,3);
    cout << subStr << end;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
abc
void test11()
{
    string string1 = "135584111117@qq.com";
    int pos = string1.find("@");
    string user =string1.substr(0,pos);
    cout << user << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
135584111117

2.1.9 案例:解析字符串
void test11()
{
    string string1 = "www.csdn.com";
    vectorv;

    int start = 0;

    int pos = -1;
    while (true)
    {
        pos = string1.find(".",start);
        if(pos == -1)
        {
            string tempStr = string1.substr(start,string1.size()-start);
            v.push_back(tempStr);
            break;
        }
        string tempStr = string1.substr(start,pos - start);
        v.push_back(tempStr);
        start = pos + 1;
    }
    for(vector::iterator it = v.begin() ; it != v.end() ; it++)
    {
        cout << *it << " " ;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
www csdn com 

2.1.10  string插入和删除操作

1.string& insert(int pos,const char * s):插入字符串

void test12()
{
    string str = "hello";
    str.insert(1,"111");
    cout << str << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
h111ello

2. string& insert(int pos,string& str):插入字符串

3. string& insert(int pos,int n,char c):在指定位置插入n个字符c

4.string& erase(int pos,int n = npos):删除从pos开始的n个字符

void test12()
{
    string str = "hello";
    str.insert(1,"111");
    cout << str << endl;
    str.erase(1,3);
    cout << str << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
h111ello
hello

2.1.11  string与c语言风格的代码转换

1.const char * &  string

void test13()
{
    const char * str = "abcd";
    string s(str);
    const char * str2 = s.c_str();
}

且const char * 可以隐式的转化为string,而反之不可以。如下代码:

void dowork(string string1)
{
    
}

void test14()
{
    const char * string1 = "hah";
    dowork(string1);
}

不报错!

void dowork(const char *  string1)
{

}

void test14()
{
    string string1 = "hah";
    dowork(string1);
}

报错!

void dowork(const char *  string1)
{

}

void test14()
{
    string string1 = "hah";
    dowork(string1.c_str());
}

不报错!

2.2 vector容器

2.2.1 vector容器的空间扩展机制

1.迭代器的空间扩展机制

相当于一个c语言中的动态数组,支持随机访问,其分配空间的方式也有特点:

void test15()
{
    vectorv;
    for(int i =0;i<10;i++)
    {
        v.push_back(i);
        cout << v.capacity() << endl;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
1
2
4
4
8
8
8
8
16
16

我们可以发现,它在动态的扩充空间。

2.动态增加大小

所谓动态增加大小,并不是在原空间之后续接新空间,而是要一块更大的内存,然后将原数据拷贝到新空间,并释放原空间。因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就失效了!类似链表!

2.2.2 vector构造函数

1.默认构造函数

2.有参构造:vector(v.begin(),v.end()); :将[v.begin(),v.end)区间的元素拷贝给自身

void printvec(vector & v)
{
    for(vector::iterator it = v.begin();it!=v.end();it++)
    {
        cout << *it << " " << endl;
    }
}

void test16()
{
    vectorv1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    vectorv2(v1.begin(),v1.end());
    printvec(v2);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
10 
20 
30 
40 
50 

3.有参构造:vector(n,elem);:将n个elem拷贝给本身

4.拷贝构造函数:vector(const vector & vec)

2.2.3 vector赋值函数

1.assign(begin,end) :将[begin,end)区间中的数据赋值给自身

void test16()
{
    vectorv1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);
    
    vectorv3;
    v3.assign(v1.begin(),v1.end());
    printvec(v3);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
10 
20 
30 
40 
50 

2.assign(n,elem):将n个elem拷贝给自身

3.vector& operator=(const vector & vec):重载等号操作符

4.swap(vec):将vec与本身的元素互换

void test16()
{
    vectorv1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    vectorv3;
    v3.assign(v1.begin(),v1.end());
    printvec(v3);
    vectorv4(10,100);
    cout << "v3 <-> v4" << endl;
    v3.swap(v4);
    cout << "v3 is :" ;
    printvec(v3);
    cout << "v4 is :" ;
    printvec(v4);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
10 
20 
30 
40 
50 
v3 <-> v4
v3 is :100 
100 
100 
100 
100 
100 
100 
100 
100 
100 
v4 is :10 
20 
30 
40 
50 

2.2.4 vector本身属性有关函数

1.size():返回个数,int类型。

2.empty():判断容器是否为空

3.resize(int num):重新指定容器的长度num,若容器变长,则以默认值填充新位置;若容器变短,则末尾超出容器的长度的元素被裁掉

void test16()
{
    vectorv1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    if(v1.empty())
    {
        cout << "v1 is empty" << endl;
    }
    else
    {
        cout << "v1 is not empty, it's size is " << v1.size() << endl;
    }
    v1.resize(10);
    printvec(v1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
v1 is not empty, it's size is 5
10 
20 
30 
40 
50 
0 
0 
0 
0 
0 
void test16()
{
    vectorv1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    if(v1.empty())
    {
        cout << "v1 is empty" << endl;
    }
    else
    {
        cout << "v1 is not empty, it's size is " << v1.size() << endl;
    }
    v1.resize(3);
    printvec(v1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
v1 is not empty, it's size is 5
10 
20 
30 

其还有一个重载版本,其第二个参数为默认值。

void test16()
{
    vectorv1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    if(v1.empty())
    {
        cout << "v1 is empty" << endl;
    }
    else
    {
        cout << "v1 is not empty, it's size is " << v1.size() << endl;
    }
    v1.resize(10,100);
    printvec(v1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
v1 is not empty, it's size is 5
10 
20 
30 
40 
50 
100 
100 
100 
100 
100 

4.capicity():容器的容量

5.reserve(int len):容器预留len个元素长度,预留位置不初始化,元素不可访问。

2.2.5 vector数据存取遍历操作

1.at(int idx):返回索引idx所指数据,如果idx越界,抛出out_of_range异常

2.operator[]:返回索引idx所指的数据,越界报错

3.front():返回容器中第一个元素

4.back():返回容器中最后一个元素

5.逆序遍历

void test16()
{
    vectorv1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    for(vector::reverse_iterator it = v1.rbegin();it!=v1.rend();it++)
    {
        cout << *it << " " ;
    }
    cout << endl;

}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
50 40 30 20 10 

6.vector的迭代器是随机访问迭代器,支持跳跃访问

void test16()
{
    vectorv1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    vector::iterator itBegin = v1.begin();
    itBegin = itBegin + 3;
    cout << *itBegin << endl;

}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
40

2.2.6 插入和删除

1.insert(const_iterator pos,int count ,ele):迭代器指向位置pos插入count个元素ele

void test16()
{
    vectorv1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    v1.insert(v1.begin(),2,100);
    printvec(v1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
100 
100 
10 
20 
30 
40 
50 

第二个参数代表个数,如果省略,那么就插一个。

2.push_back(ele):尾部插入元素ele

3.pop_back():删除最后一个元素

4.erase(const_iterator start,const_iterator end):删除迭代器从start到end之间的元素

5.erase(const_iterator pos):删除迭代器指向的元素

/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
100 100 10 20 30 40 50 
v1 is not empty, it's size is 7
100 100 10 20 30 40 50 100 100 100 
100 100 10 20 30 40 50 100 100 
100 10 20 30 40 50 100 100 

6.clear():删除容器中所有元素

等价于erase(v.begin(),v.end())

2.2.7 案例1:巧用swap收缩内存

1.看下面代码

void test17()
{
    vectorv;
    for(int i=0;i<100000;i++)
    {
        v.push_back(i);
    }
    cout << "v.capacity is :" << v.capacity() << endl;
    cout << "v.size is :" << v.size() << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
v.capacity is :131072
v.size is :100000

2.我们对其进行resize

void test17()
{
    vectorv;
    for(int i=0;i<100000;i++)
    {
        v.push_back(i);
    }
    cout << "v.capacity is :" << v.capacity() << endl;
    cout << "v.size is :" << v.size() << endl;
    v.resize(3);
    cout << "v.capacity is :" << v.capacity() << endl;
    cout << "v.size is :" << v.size() << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
v.capacity is :131072
v.size is :100000
v.capacity is :131072
v.size is :3

我们发现,size缩小到了3,但容量没变。

那么有很大的内存被浪费了。。。

3.巧用swap收割内存

void test17()
{
    vectorv;
    for(int i=0;i<100000;i++)
    {
        v.push_back(i);
    }
    cout << "v.capacity is :" << v.capacity() << endl;
    cout << "v.size is :" << v.size() << endl;
    v.resize(3);
    cout << "v.capacity is :" << v.capacity() << endl;
    cout << "v.size is :" << v.size() << endl;
    vector(v).swap(v);
    cout << "v.capacity is :" << v.capacity() << endl;
    cout << "v.size is :" << v.size() << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
v.capacity is :131072
v.size is :100000
v.capacity is :131072
v.size is :3
v.capacity is :3
v.size is :3

我们来解释一下这段代码:

我们原来创建了很大的空间,但最后才发现只用了三个。其余空间都被浪费掉了。

vector(v) 表示创建一个匿名对象,用v初始化这个匿名对象,并用v的size赋给匿名对象的size。

后面加一个swap是将匿名对象与v的空间的指针做一个交换,使得匿名对象指向原先的131072的空间,指向3个capacity的空间,而匿名对象有个特点,这行执行完之后自动释放内容

2.2.8 案例2:巧用reserve预留空间

1.读取下面代码

void test18()
{
    vectorv;
    
    int * p = NULL;
    int num = 0;
    for(int i = 0;i < 1000000;i++)
    {
        v.push_back(i);
        if(p != &v[0])
        {
            p = &v[0];
            num++;
        }
    }
    cout << "total space allocate is " << num << endl;
}

由于vector容器在不断的动态分配空间,每次新增空间都要找一块新的内存地址,因此这段代码的用处就是让p指针时刻指向容器的首地址,并且用num来记录重新分配内存的次数。

/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
total space allocate is 21

 2.用reserve预留空间

void test18()
{
    vectorv;
    v.reserve(100000);
    int * p = NULL;
    int num = 0;
    for(int i = 0;i < 1000000;i++)
    {
        v.push_back(i);
        if(p != &v[0])
        {
            p = &v[0];
            num++;
        }
    }
    cout << "total space allocate is " << num << endl;
}

开始就预留了100000个空间,避免了内存消耗。

/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
total space allocate is 21

2.3 deque容器

2.3.1 deque容器简介

        类似数据结构的队列,可以两边进两边出。

        其相当于vector容器,没有容量的概念

2.3.2 构造函数

1.默认构造函数

2.有参构造:deque(v.begin(),v.end()); :将[v.begin(),v.end)区间的元素拷贝给自身

void printvec(deque & v)
{
    for(deque::iterator it = v.begin();it!=v.end();it++)
    {
        cout << *it << " " << endl;
    }
}

void test16()
{
    dequev1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    dequev2(v1.begin(),v1.end());
    printvec(v2);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
10 
20 
30 
40 
50 

3.有参构造:deque(n,elem);:将n个elem拷贝给本身

4.拷贝构造函数:deque(const queue & deq)

2.3.3 deque赋值函数

1.assign(begin,end) :将[begin,end)区间中的数据赋值给自身

void test16()
{
    dequev1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);
    
    dequev3;
    v3.assign(v1.begin(),v1.end());
    printvec(v3);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
10 
20 
30 
40 
50 

2.assign(n,elem):将n个elem拷贝给自身

3.deque& operator=(const vector & vec):重载等号操作符

4.swap(vec):将vec与本身的元素互换

void test16()
{
    dequev1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    dequev3;
    v3.assign(v1.begin(),v1.end());
    printvec(v3);
    dequev4(10,100);
    cout << "v3 <-> v4" << endl;
    v3.swap(v4);
    cout << "v3 is :" ;
    printvec(v3);
    cout << "v4 is :" ;
    printvec(v4);
}

5.若我们不想让print操作我们的数据,我们可以在形参加上关键字const,同时变化迭代器为只读迭代器

void printdeq(const deque & v)
{
    for(deque::const_iterator it = v.begin();it!=v.end();it++)
    {
        // *it = 1000;
        cout << *it << " " << endl;
    }
}

void test16()
{
    dequev1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    dequev2(v1.begin(),v1.end());
    printdeq(v2);
}

2.3.4 vector本身属性有关函数

1.size():返回个数,int类型。

2.empty():判断容器是否为空

3.resize(int num):重新指定容器的长度num,若容器变长,则以默认值填充新位置;若容器变短,则末尾超出容器的长度的元素被裁掉

void test16()
{
    dequev1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    if(v1.empty())
    {
        cout << "v1 is empty" << endl;
    }
    else
    {
        cout << "v1 is not empty, it's size is " << v1.size() << endl;
    }
    v1.resize(10);
    printdeq(v1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
v1 is not empty, it's size is 5
10 
20 
30 
40 
50 
0 
0 
0 
0 
0 
void test16()
{
    dequev1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    if(v1.empty())
    {
        cout << "v1 is empty" << endl;
    }
    else
    {
        cout << "v1 is not empty, it's size is " << v1.size() << endl;
    }
    v1.resize(3);
    printdeq(v1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
v1 is not empty, it's size is 5
10 
20 
30 

其还有一个重载版本,其第二个参数为默认值。

void test16()
{
    dequev1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    if(v1.empty())
    {
        cout << "v1 is empty" << endl;
    }
    else
    {
        cout << "v1 is not empty, it's size is " << v1.size() << endl;
    }
    v1.resize(10,100);
    printdeq(v1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
v1 is not empty, it's size is 5
10 
20 
30 
40 
50 
100 
100 
100 
100 
100 

4.capicity():容器的容量

5.reserve(int len):容器预留len个元素长度,预留位置不初始化,元素不可访问。

2.3.5 vector数据存取遍历操作

1.at(int idx):返回索引idx所指数据,如果idx越界,抛出out_of_range异常

2.operator[]:返回索引idx所指的数据,越界报错

3.front():返回容器中第一个元素

4.back():返回容器中最后一个元素

5.逆序遍历

void test16()
{
    queuev1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    for(queue::reverse_iterator it = v1.rbegin();it!=v1.rend();it++)
    {
        cout << *it << " " ;
    }
    cout << endl;

}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
50 40 30 20 10 

6.vector的迭代器是随机访问迭代器,支持跳跃访问

void test16()
{
    queuev1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);

    queue::iterator itBegin = v1.begin();
    itBegin = itBegin + 3;
    cout << *itBegin << endl;

}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
40

2.3.6 插入和删除

1.push_back(elem):在容器的尾部加一个数据

2.push_front(elem):在容器的头部加一个数据

3.pop_back():删除容器最后一个数据

4.pop_front():删除容器第一个数据

void test19()
{
    dequedeq;
    deq.push_back(10);
    deq.push_back(20);
    deq.push_back(30);
    deq.push_front(40);
    printdeq(deq);
    deq.pop_back();
    printdeq(deq);
    deq.pop_front();
    printdeq(deq);
}

int main() {
    test19();
    return 0;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
40 10 20 30 
40 10 20 
10 20 

5.insert(pos,elem):在pos位置插入一个elem元素的拷贝,返回新元素的位置

void test19()
{
    dequedeq;
    deq.push_back(10);
    deq.push_back(20);
    deq.push_back(30);
    deq.push_front(40);
    deq.insert(deq.begin()+2,1000);
    printdeq(deq);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
40 10 1000 20 30 

6.insert(pos,n,elem):在pos位置插入n个elem元素的拷贝,返回值为空

void test19()
{
    dequedeq;
    deq.push_back(10);
    deq.push_back(20);
    deq.push_back(30);
    deq.push_front(40);
    deq.insert(deq.begin()+2,3,1000);
    printdeq(deq);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
40 10 1000 1000 1000 20 30

7.insert(pos,begin,end):在pos位置插入[begin,end)区间的数据,返回下一个数据的位置

void test19()
{
    dequedeq;
    deq.push_back(10);
    deq.push_back(20);
    deq.push_back(30);
    deq.push_front(40);
    deque::iterator fa = deq.insert(deq.begin()+2,deq.begin(),deq.end()-1);
    printdeq(deq);
    cout << "next data is :" << *fa << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
40 10 40 10 20 20 30 
next data is :40

分析:我们插入了 40 10 20 30

在10后面插入 40 10 20 即 40 10 40 10 20 20 30 ,返回10后面的20.

8.clear():移除容器内所有数据

9.erase(beg,end):删除[beg,end)区间的数据,返回下一个数据

10.erase(pos):删除pos位置的数据,返回

2.3.7 案例:利用容器实现评委打分

1.需求

有5名选手ABCDE,10个评委为其打分,去除最高分最低分,取平均分。

2. code

class Player
{
public:
    Player(string name,int age)
    {
        this -> name = name;
        this -> score = score;
    }
    void giveScore(int score)
    {
        this -> score = score;
    }
    string getName()
    {
        return name;
    }
    int showsscore()
    {
        return score;
    }
private:
    string name;
    int score;
};


void createPlayer(vector & player)
{
    string nameSeed = "ABCDE";
    for(int i =0 ; i<5 ; i++)
    {
        string name = "xuanshou";
        name += nameSeed[i];
        int score = 0;
        Player player1(name,score);
        player.push_back(player1);
    }
}

void setScore(vector & player)
{
    for(vector::iterator it = player.begin();it != player.end();it++)
    {
        dequed;
        for(int i=0;i<10;i++)
        {
            int score = rand()%40 + 60;
            d.push_back(score);
        }
        cout << "-------------------" <<  (*it).getName()  << "Score--------------------------" << endl;
        for(deque::iterator dit = d.begin();dit!=d.end();dit++)
        {
            cout << *dit << " " ;
        }
        cout << endl;
        sort(d.begin(),d.end());
        d.pop_front();
        d.pop_back();
        int sumScore = 0;
        int avrScore;
        for(deque::iterator dit = d.begin();dit!=d.end();dit++)
        {
            sumScore += *dit;
        }
        avrScore = sumScore / 8;
        (*it).giveScore(avrScore);
    }
}

void showScore(vector player)
{
    for(vector::iterator it = player.begin();it != player.end();it++)
    {
        cout << (*it).getName() << "'s score is : " << (*it).showsscore() << endl;
    }
}


void test20()
{
    vector v;
    createPlayer(v);
    setScore(v);
    showScore(v);
}
-------------------xuanshouBScore--------------------------
62 87 70 79 63 66 80 86 72 76 
-------------------xuanshouCScore--------------------------
71 68 67 89 82 70 82 63 87 75 
-------------------xuanshouDScore--------------------------
69 62 82 78 89 67 93 76 71 62 
-------------------xuanshouEScore--------------------------
89 73 81 99 84 77 98 64 95 70 
xuanshouA's score is : 79
xuanshouB's score is : 74
xuanshouC's score is : 75
xuanshouD's score is : 74
xuanshouE's score is : 83

2.4 stack栈容器

2.4.1 stack容器基本概念

stack容器是一种先进后出的数据结构,它只有一个出口。其允许新增元素,移除元素,获取栈顶元素,但是除了顶端外,没有任何方法可以存取stack的其他元素。即stack不允许有遍历行为,于是也没有迭代器。

2.4.2 栈的构造函数

1.默认构造函数

2.拷贝构造函数

2.4.3 栈的其余接口

1.push:入栈

2.empty:是否为空

3.top:获取栈顶元素

4.pop:出栈

5.size:栈元素的个数

void test21()
{
    stack s;
    s.push(10);
    s.push(20);
    s.push(30);
    s.push(40);
    cout << "s.size = " << s.size() << endl ;
    int i = s.size();
    while(!s.empty())
    {
        cout << "data" << i << " is : " << s.top() << endl;
        s.pop();
        i--;
    }
    cout << "s.size = " << s.size() << endl ;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
s.size = 4
data4 is : 40
data3 is : 30
data2 is : 20
data1 is : 10
s.size = 0

2.5 queue队列容器

2.5.1 queue容器基本简介

queue是一种先进先出的数据结构,它有两个出口,queue容器允许从一端新增元素,一端移除元素。

没有迭代器!

2.5.2 队列的一些接口
void test22()
{
    queueq;
    Person p1("aaa",10);
    Person p2("bbb",20);
    Person p3("ccc",30);
    Person p4("ddd",40);
    q.push(p1);
    q.push(p2);
    q.push(p3);
    q.push(p4);
    while (!q.empty())
    {
        cout << "队头元素 : " <<  q.front().name << "  ";
        cout << "队尾元素 : " <<  q.back().name << endl;
        q.pop();
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
队头元素 : aaa  队尾元素 : ddd
队头元素 : bbb  队尾元素 : ddd
队头元素 : ccc  队尾元素 : ddd
队头元素 : ddd  队尾元素 : ddd

2.6 list容器

2.6.1 list简介

        链表是由一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑性是通过链表中的指针接续次序实现的。链表中由一系列节点组成,节点可以在运行时动态生成。每个节点包含两部分:一个是存储数据元素的数据域,一个是存储下一个节点地址的指针域。

        其相比于vector来说,list一次只分配一个空间,不会造成浪费。

        list在stl中是一个双向循环链表。(可以看看数据结构的解释)

2.6.2 list的迭代器

2.6.3 list构造函数

1. 正逆序访问迭代器内容

void test23()
{
    list L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    for(list::iterator it = L1.begin();it!=L1.end();it++)
    {
        cout << *it << " " << endl;
    }
    cout << endl;

    for(list::reverse_iterator it = L1.rbegin();it!=L1.rend();it++)
    {
        cout << *it << " " << endl;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
10 
20 
30 
40 

40 
30 
20 
10 

2.list迭代器不支持随机访问

2.6.4 list元素插入和删除操作

1.接口介绍

 

2.代码测试一

void printList(const list L1)
{
    cout << "-----------------正序----------------" << endl;
    for(list::const_iterator it = L1.begin();it!=L1.end();it++)
    {
        cout << *it << " " ;
    }
    cout << endl;

    cout << "-----------------反序----------------" << endl;
    for(list::const_reverse_iterator it = L1.rbegin();it!=L1.rend();it++)
    {
        cout << *it << " " ;
    }
    cout << endl;

}

void test23()
{
    list L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    printList(L1);
    L1.push_front(50);
    printList(L1);
    L1.pop_back();
    printList(L1);
    L1.pop_front();
    printList(L1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
-----------------正序----------------
10 20 30 40 
-----------------反序----------------
40 30 20 10 
-----------------正序----------------
50 10 20 30 40 
-----------------反序----------------
40 30 20 10 50 
-----------------正序----------------
50 10 20 30 
-----------------反序----------------
30 20 10 50 
-----------------正序----------------
10 20 30 
-----------------反序----------------
30 20 10 

3.代码测试二

void test24()
{
    list L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    printList(L1);

    L1.insert(L1.begin(),1000);
    printList(L1);

    L1.erase(L1.begin());
    printList(L1);

    L1.remove(30);
    printList(L1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
-----------------正序----------------
10 20 30 40 
-----------------正序----------------
1000 10 20 30 40 
-----------------正序----------------
10 20 30 40 
-----------------正序----------------
10 20 40 

2.6.5 list大小、赋值、数据存取操作

1.接口介绍

2.code1

void test26()
{
    list L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);
    L1.reverse();
    printList(L1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
-----------------正序----------------
40 30 20 10 

3.code2

对于排序算法来说,如果容器迭代器支持随机访问,可以使用系统默认的标志算法。

不支持随机访问的迭代器的容器,内部会提供对应的算法接口。

void test26()
{
    list L1;
    L1.push_back(10);
    L1.push_back(8);
    L1.push_back(3);
    L1.push_back(7);

    L1.sort();
    printList(L1);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
-----------------正序----------------
3 7 8 10 

4.code3

对于自定义类型的数据必须指定排序规则

void test27()
{
    list L;
    Person p1("athe",40);
    Person p2("zhaoyun",38);
    Person p3("xiaoqiao",18);
    Person p4("luban",1);
    Person p5("pamgu",66666);
    L.push_back(p1);
    L.push_back(p2);
    L.push_back(p3);
    L.push_back(p4);
    L.push_back(p5);
    L.sort(myComPerson);
    for(list::iterator it = L.begin() ; it != L.end() ; it++)
    {
        cout << (*it).name << " 's age is " << (*it).age << endl;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
pamgu 's age is 66666
athe 's age is 40
zhaoyun 's age is 38
xiaoqiao 's age is 18
luban 's age is 1

5.code4

class Person
{
public:
    Person(string name,int age,int height)
    {
        this -> age = age;
        this ->name = name;
        this ->height = height;
    }
    int age;
    string name;
    int height;
};

需求:若年龄相等,按身高升序排序。

bool myComPerson(Person & p1,Person & p2)
{
    if(p1.age == p2.age)
    {
        return p1.age < p2.age;
    }
    return p1.age > p2.age;
}

void test27()
{
    list L;
    Person p1("athe",4,181);
    Person p2("zhaoyun",38,125);
    Person p3("xiaoqiao",18,174);
    Person p4("luban",1,62);
    Person p5("pamgu",66666,25);
    Person p6("jin",66666,62);
    Person p7("hebang",66666,624);
    L.push_back(p1);
    L.push_back(p2);
    L.push_back(p3);
    L.push_back(p4);
    L.push_back(p5);
    L.push_back(p6);
    L.push_back(p7);
    L.sort(myComPerson);
    for(list::iterator it = L.begin() ; it != L.end() ; it++)
    {
        cout << (*it).name << " 's age is " << (*it).age << endl;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
pamgu 's age is 66666
jin 's age is 66666
hebang 's age is 66666
zhaoyun 's age is 38
xiaoqiao 's age is 18
athe 's age is 4
luban 's age is 1

6.若要删除一个人数据,不可直接调用L.remove(p1),必须要写重载==号

class Person
{
public:
    Person(string name,int age,int height)
    {
        this -> age = age;
        this ->name = name;
        this ->height = height;
    }
    bool operator==(const Person & p)
    {
        if(this->name==name&& this->age == age && this->height == height)
        {
            return true;
        }
        return false;
    }
    int age;
    string name;
    int height;
};

2.7 set容器

2.7.1 set容器基本概念

1.set

2.multiset

2.7.2 set容器常用API

1.常用api介绍

 

 

 

2.code1

void test28()
{
    sets;
    s.insert(5);
    s.insert(7);
    s.insert(3);
    s.insert(9);
    for(set::iterator it  = s.begin();it!=s.end();it++)
    {
        cout << *it << " " ;
    }

}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
3 5 7 9 
进程已结束,退出代码0

插入的时候已经做好了排序!

3.code2

void printset(set s)
{
    for(set::iterator it  = s.begin(); it!= s.end();it++)
    {
        cout << *it << " " ;
    }
    cout << endl;
}

void test28()
{
    sets;
    s.insert(5);
    s.insert(7);
    s.insert(3);
    s.insert(9);
    printset(s);

    s.erase(7);
    printset(s);
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
3 5 7 9 
3 5 9 

4.code3

void test29()
{
    sets;
    s.insert(5);
    s.insert(7);
    s.insert(3);
    s.insert(9);
    s.insert(9);
    //插入了重复值不会报错,而是插了白插
    set::iterator pos = s.find(3);
    if(pos!=s.end())
    {
        cout << "successfully find " << *pos << endl;
    }
    else
    {
        cout << "failed to find!" << endl;
    }

    int num = s.count(9);
    cout << "9's count is " << num << endl;
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
successfully find 3
9's count is 1

5.code4

void test30()
{
    sets;
    s.insert(5);
    s.insert(7);
    s.insert(3);
    s.insert(9);
    s.insert(1);
    s.insert(4);
    s.insert(11);
    s.insert(0);

    set::iterator it = s.lower_bound(4);
    if(it!=s.end())
    {
        cout << "successfully find a numer(lower_bound) >= 4 : " << *it << endl;
    }
    else
    {
        cout << "fail to find a numer >= 4 : " << endl;
    }

    set::iterator it1 = s.upper_bound(4);
    if(it!=s.end())
    {
        cout << "successfully find a numer(upper_bound) > 4 : " << *it1 << endl;
    }
    else
    {
        cout << "fail to find a numer > 4 : " << endl;
    }

    pair::iterator,set::iterator> ret = s.equal_range(3);
    if(ret.first!=s.end())
    {
        cout << "eqlrange_ist : successfully find a numer(lower_bound) >= 3 : " << *ret.first << endl;
    }
    else
    {
        cout << "eqlrange_ist : fail to find a numer(lower_bound) >= 3 : ";
    }
    if(ret.second!=s.end())
    {
        cout << "eqlrange_2nd : successfully find a numer(upper_bound) > 3 : " << *ret.second << endl;
    }
    else
    {
        cout << "eqlrange_2nd : fail to find a numer(upper_bound) >= 3 : ";

    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
successfully find a numer(lower_bound) >= 4 : 4
successfully find a numer(upper_bound) > 4 : 5
eqlrange_ist : successfully find a numer(lower_bound) >= 3 : 3
eqlrange_2nd : successfully find a numer(upper_bound) > 3 : 4

2.7.3 pair对组的创建

1.初始化方法1

void test31()
{
    pair p("Tom",10);
    cout << p.first << ":" << p.second;
}

 2.初始化方法2

    pair p2 = make_pair("Jerry",10);

2.7.4 一些问题

1.插入重复值处理:系统维护一个pair对,::iterator,bool>,通过第二个判断是否插入成功

void test32()
{
    set s;
    pair::iterator,bool> ret = s.insert(10);
    if(ret.second)
    {
        cout << "first insert successfully!" << endl;
    }
    else
    {
        cout << "first insert failed!" << endl;
    }
    ret = s.insert(10);
    if(ret.second)
    {
        cout << "second insert successfully!" << endl;
    }
    else
    {
        cout << "second insert failed!" << endl;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
first insert successfully!
second insert failed!

但multiset允许插入重复的。

2.如何让其从大到小排序1:需要重载()

class mycompareint
{
public:
    bool operator()(int v1,int v2)
    {
        return v1>v2;
    }
};

void test33()
{
    set s;
    s.insert(5);
    s.insert(7);
    s.insert(3);
    s.insert(9);
    s.insert(1);
    s.insert(4);
    s.insert(11);
    s.insert(0);
    for(set::iterator it = s.begin();it!=s.end();it++)
    {
        cout << *it << " ";
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
11 9 7 5 4 3 1 0 
进程已结束,退出代码0

3.如何让其从大到小排序2:自定义数据类型--需要重载() 

class mmmm
{
public:
    bool operator()(const myPerson & p1 ,const myPerson & p2)
    {
        return p1.age < p2.age ;
    }
};

void test34()
{
    sets;
    myPerson p1("li",79);
    myPerson p2("wang",38);
    myPerson p3("hao",47);
    myPerson p4("jian",20);
    myPerson p5("ggking",21);
    s.insert(p1);
    s.insert(p2);
    s.insert(p3);
    s.insert(p4);
    s.insert(p5);
    for(set::iterator it=s.begin();it!=s.end();it++)
    {
        cout << "name is : " << (*it).name << "   age is : " << (*it).age << endl;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
name is : jian   age is : 20
name is : ggking   age is : 21
name is : wang   age is : 38
name is : hao   age is : 47
name is : li   age is : 79

2.8 map容器

2.8.1 基本概念

2.8.2 常用API

1.常用API

 

 

2.code1

void test35()
{
    map m;
    m.insert(pair(1,1));
    m.insert(make_pair(2,20));
    m.insert(map::value_type(3,30));
    m[4] = 40;
    m[5];
    for(map::iterator it = m.begin();it!=m.end();it++)
    {
        cout << "key = " << it->first << " ;value = " << it->second << endl;
    }
}
/home/liuhongwei/桌面/slam/stlday1/cmake-build-debug/stlday1
key = 1 ;value = 1
key = 2 ;value = 20
key = 3 ;value = 30
key = 4 ;value = 40
key = 5 ;value = 0

可以看出,对于第四种插入方式,如果不创建value值,则为0。

2.9 STL容器使用时机

1.典型存储结构及是否能随机读写

2.元素搜寻速度及安插删除

3.使用场景

 

4.一个例子

需求:

代码:

#include 
#include 
#include 

using namespace std;

enum {CAIWU,RENLI,YANFA};

class Worker
{
public:
    void setName(string name)
    {
        this -> name = name;
    }
    void setSalary(int salary)
    {
        this -> money = salary;
    }
    string getName()
    {
        return this->name;
    }
    int getSalary()
    {
        return this -> money;
    }
private:
    string name;
    int money;
};

void createWorker(vector&v)
{
    string seed = "ABCDE";
    string temp = "worker";
    for(int i=0;i<5;i++)
    {
        Worker worker;
        worker.setName(temp + seed[i]);
        worker.setSalary(rand()%10000+10000);
        v.push_back(worker);
    }
}

void printWorker(vector&v)
{
    for(vector::iterator it = v.begin();it!=v.end();it++)
    {
        cout << "Worker's name is :" << (*it).getName() << "   Worker's salary is " << (*it).getSalary() << endl;
    }
}

void setGroup(vector &v,multimap& m)
{
    for(vector::iterator it = v.begin();it!=v.end();it++)
    {
        //random 0 1 2
        int depID = rand()%3;
        m.insert(make_pair(depID,*it));
    }
}

void showWorker(multimap & m)
{
    cout << "财务部门员工如下" << endl;
    multimap::iterator pos = m.find(CAIWU);
    int num = m.count(CAIWU);
    int index = 0;
    for(;pos!=m.end(),indexsecond.getName() << "    Salary is : " << pos->second.getSalary() << endl;
    }

    cout << "人力部门员工如下" << endl;
    pos = m.find(RENLI);
    num = m.count(RENLI);
    index = 0;
    for(;pos!=m.end(),indexsecond.getName() << "    Salary is : " << pos->second.getSalary() << endl;
    }

    cout << "研发部门员工如下" << endl;
    pos = m.find(YANFA);
    num = m.count(YANFA);
    index = 0;
    for(;pos!=m.end(),indexsecond.getName() << "    Salary is : " << pos->second.getSalary() << endl;
    }
}

int main() {
    srand((unsigned int) time(NULL));
    vector v;
    createWorker(v);
    printWorker(v);
    multimap m;
    setGroup(v,m);
    showWorker(m);
    return 0;
}
/home/liuhongwei/桌面/slam/stlday2/cmake-build-debug/stlday2
Worker's name is :workerA   Worker's salary is 10491
Worker's name is :workerB   Worker's salary is 10226
Worker's name is :workerC   Worker's salary is 12469
Worker's name is :workerD   Worker's salary is 18742
Worker's name is :workerE   Worker's salary is 18270
财务部门员工如下
Name is : workerB    Salary is : 10226
人力部门员工如下
Name is : workerE    Salary is : 18270
研发部门员工如下
Name is : workerA    Salary is : 10491
Name is : workerC    Salary is : 12469
Name is : workerD    Salary is : 18742

3 常用算法

3.1 函数对象

3.1.1 函数对象

1.函数对象的本质

2.code1

本质是一个类的对象,因此称为函数对象,也叫仿函数

class myPrint
{
public:
    void operator()(int num)
    {
        cout << num << endl;
    }
};

void test01()
{
    myPrint my;
    my(100);
}


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

3.code2

函数对象超出了普通函数的概念,可以拥有自己的状态。

class myPrint
{
public:
    void operator()(int num)
    {
        cout << num << endl;
        count++;
    }
    int count = 0;
};

void test01()
{
    myPrint my;
    my(100);
    my(100);
    my(100);
    my(100);
    cout << "time is " << my.count << endl;

}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
100
100
100
100
time is 4

4.code3

函数对象可以作为函数参数

void doPrint(myPrint myprint,int num)
{
    myprint(num);
}

void test03()
{
    doPrint(myPrint(),1000);
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
1000

3.1.2 谓词

1.定义

2.一元谓词

代码解释:find_if功能,在v.begin与v.end之间寻找一个满足匿名对象要求的数据并返回指向数据的一个迭代器。此例中,10>20不成立,20>20不成立,30>20成立,返回指向30的迭代器对象。

class Greaterthan20
{
public:
    bool operator()(int val)
    {
        return val>20;
    }
};

void test04()
{
    vector v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
    vector::iterator it = find_if(v.begin(),v.end(),Greaterthan20());
    if(it != v.end())
    {
        cout << "find a number > 20,it's : " << *it << endl;
    }
    else
    {
        cout << "can't find" << endl;
    }
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
find a number > 20,it's : 30

3.二元谓词

void myPrintint(int val)
{
    cout << val << " " ;
}

class mycompare
{
public:
    bool operator()(int v1,int v2)
    {
        return v1>v2;
    }
};

void test05()
{
    vector v;
    v.push_back(10);
    v.push_back(30);
    v.push_back(20);
    v.push_back(50);
    v.push_back(40);
    sort(v.begin(),v.end());
    for_each(v.begin(),v.end(),myPrintint);
    cout << endl;
    sort(v.begin(),v.end(),mycompare());
    for_each(v.begin(),v.end(), myPrintint);
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
10 20 30 40 50 
50 40 30 20 10 
进程已结束,退出代码0

3.1.3 内建函数对象

1.类型:需要引入头文件functional

2.code1

void test06()
{
    negaten;
    cout << n(10) << endl;

    plusp;
    cout << p(10,10) << endl;

    vectorv;
    v.push_back(10);
    v.push_back(30);
    v.push_back(20);
    v.push_back(50);
    v.push_back(40);
    // big to small
    sort(v.begin(),v.end(),greater());
    for_each(v.begin(),v.end(), myPrintint);

}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
-10
20
50 40 30 20 10 

3.1.4 适配器

1.使用场景

看如下代码:

class printint
{
public:
    void operator()(int val)
    {
        cout << val << " " ;
    }

};

void test07()
{
    vectorv;
    for(int i=0;i<10;i++)
    {
        v.push_back(i);
    }
    for_each(v.begin(),v.end(), printint());
}

这个函数的功能是遍历vector容器的内容,从开始到结束,遍历每个元素时调用回调函数(这里为仿函数,确切来说是一个匿名对象),但此时,我要用户对每个数据操作该怎么办?可以在()重载下手,比如让val+100。但可不可以从printint下手呢,让其传入两个参数,但foreach底层实现只能传入一个参数,于是我们采用适配器将两者绑定。

2.函数对象适配器bind2nd的使用

I.引入头文件

#include 

II.用bind2nd进行绑定

void test07()
{
    vectorv;
    for(int i=0;i<10;i++)
    {
        v.push_back(i);
    }
    cout << "Please input a number : " ;
    int num;
    cin >> num;
    for_each(v.begin(),v.end(), bind2nd(printint(),num));
}

III.继承 参数1类型,参数2类型,返回值参数

class printint : public binary_function
{
public:
    void operator()(int val,int start)
    {
        cout << val + start << " " ;
    }

};

IV.加const,执行

/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
Please input a number : 25
25 26 27 28 29 30 31 32 33 34 

V.bind1st与bind2nd区别:绑定顺序相反,不推荐用。

class printint : public binary_function
{
public:
    void operator()(int val,int start)const
    {
        cout << "val + start = " << val + start << " " << "val = " << val << " start = " << start << endl ;
    }

};

void test07()
{
    vectorv;
    for(int i=0;i<10;i++)
    {
        v.push_back(i);
    }
    cout << "Please input a number : " ;
    int num;
    cin >> num;
    for_each(v.begin(),v.end(), bind2nd(printint(),num));
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
Please input a number : 10
val + start = 10 val = 0 start = 10
val + start = 11 val = 1 start = 10
val + start = 12 val = 2 start = 10
val + start = 13 val = 3 start = 10
val + start = 14 val = 4 start = 10
val + start = 15 val = 5 start = 10
val + start = 16 val = 6 start = 10
val + start = 17 val = 7 start = 10
val + start = 18 val = 8 start = 10
val + start = 19 val = 9 start = 10
class printint : public binary_function
{
public:
    void operator()(int val,int start)const
    {
        cout << "val + start = " << val + start << " " << "val = " << val << " start = " << start << endl ;
    }

};

void test07()
{
    vectorv;
    for(int i=0;i<10;i++)
    {
        v.push_back(i);
    }
    cout << "Please input a number : " ;
    int num;
    cin >> num;
    for_each(v.begin(),v.end(), bind1st(printint(),num));
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
Please input a number : 10
val + start = 10 val = 10 start = 0
val + start = 11 val = 10 start = 1
val + start = 12 val = 10 start = 2
val + start = 13 val = 10 start = 3
val + start = 14 val = 10 start = 4
val + start = 15 val = 10 start = 5
val + start = 16 val = 10 start = 6
val + start = 17 val = 10 start = 7
val + start = 18 val = 10 start = 8
val + start = 19 val = 10 start = 9

3.取反适配器not1的使用

I.需求:寻找大于5的数取反

II.用not1进行绑定

    vector::iterator it = find_if(v.begin(),v.end(), not1(GreaterthanFive()));

III.继承 参数1类型,返回值参数

class GreaterthanFive : public unary_function 
{
public:
    bool operator()(int val) const
    {
        return val > 5;
    }
};

IV.加const,执行

class GreaterthanFive : public unary_function 
{
public:
    bool operator()(int val) const
    {
        return val > 5;
    }
};


void test08()
{
    vectorv;
    for(int i=0;i<10;i++)
    {
        v.push_back(i);
    }
    vector::iterator it = find_if(v.begin(),v.end(), not1(GreaterthanFive()));
    if(it!=v.end())
    {
        cout << *it << endl;
    }
    else
    {
        cout << "can't find a number" << endl;
    }

}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
0

找到了小于5的数字(原本是寻找大于5的数字)

V .改进,让用户决策

void test08()
{
    vectorv;
    for(int i=0;i<10;i++)
    {
        v.push_back(i);
    }
    int num;
    cout << "Input a number , find a number < it : " ;
    cin >> num ;

    vector::iterator it = find_if(v.begin(),v.end(), not1(bind2nd(greater(),num)));
    if(it!=v.end())
    {
        cout << *it << endl;
    }
    else
    {
        cout << "can't find a number" << endl;
    }

}

代码解释:在begin与end之间迭代,返回一个迭代器;这个迭代器的回调函数的意思是:返回大于num的数字,再取相反,即找到第一个小于num的数字。

4.函数适配器的使用

I.函数没有类的继承,怎么去做适配呢?

void myprintint(int val,int start)
{
    cout << val+start << " " ;
}

void test09()
{
    vectorv;
    for(int i=0;i<10;i++)
    {
        v.push_back(i);
    }
    for_each(v.begin(),v.end(), bind2nd(ptr_fun(myprintint),1000));
}

5.成员函数适配器

I.用普通函数实现打印成员函数

void myprintPerson(Person & person)
{
    cout << "Name is : " << person.name << "  Age is : " << person.age << endl;
}

void test10()
{
    vectorv;
    Person p1("a",100);
    Person p2("b",200);
    Person p3("c",300);
    Person p4("d",400);
    Person p5("e",500);
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);
    v.push_back(p4);
    v.push_back(p5);
    for_each(v.begin(),v.end(), myPrintint);

}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
Name is : a  Age is : 100
Name is : b  Age is : 200
Name is : c  Age is : 300
Name is : d  Age is : 400
Name is : e  Age is : 500

进程已结束,退出代码0

6.总结

3.2 常用算法介绍

3.2.1 常用遍历算法

1.for_each介绍:包含在algorithm头文件

2.transform介绍

3.code1 :for_each返回值介绍

class myPrint1
{
public:
    void operator()(int val)
    {
        cout << val << " ";
        count ++;
    }
    int count = 0;
};

void test11()
{
    vectorv;
    for(int i = 0;i<10;i++)
    {
        v.push_back(i);
    }
    myPrint1 print = for_each(v.begin(),v.end(),myPrint1());
    cout << endl <<  "count = " << print.count << endl;
}

4.code2: for_each可以绑定参数输出

class myPrint2 : public binary_function
{
public:
    void operator()(int val,int start)const
    {
        cout << val + start << " ";
    }
};

void test12()
{
    vectorv;
    for(int i = 0;i<10;i++)
    {
        v.push_back(i);
    }
    for_each(v.begin(), v.end(), bind2nd(myPrint2(), 100));
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
100 101 102 103 104 105 106 107 108 109 
进程已结束,退出代码0

5.code3:transform介绍

class myTransform
{
public:
    int operator()(int val)
    {
        return val + 10000;
    }
};

void test13()
{
    vectorv;
    vectorv2;

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

    v2.resize(v.size());
    transform(v.begin(),v.end(),v2.begin(),myTransform());
    for_each(v2.begin(),v2.end(),[](int val){cout << val << " ";});
}

因为v的容器在不断扩充的过程中容量不断增多,但v2的容量创建时为0,直接加数据会导致崩溃!因此要先去扩容!

3.2.2 常用查找算法

1.find_if与find

2.code1:find查找内置数据类型

void test14()
{
    vectorv;
    for(int i = 0;i<10;i++)
    {
        v.push_back(i);
    }
    vector::iterator it = find(v.begin(),v.end(),5);
    if(it != v.end())
    {
        cout << "Just find number " << *it << endl;
    }
    else
    {
        cout << "Failed to find number 5 !" << endl;
    }

}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
Just find number 5

3.code2:find查找自定义数据类型 : 需要重载 ==

class Person
{
public:
    string name;
    int age;
    Person(string name,int age)
    {
        this -> name = name;
        this -> age = age;
    }
    void myprintPerson()
    {
        cout << "Name is : " << this->name << "  Age is : " << this->age << endl;
    }
    bool operator==(const Person & person)
    {
        return ((this->name == person.name)&&(this->age == person.age)) ;
    }
};

void test01()
{
    vectorv;
    Person p1("a",100);
    Person p2("b",200);
    Person p3("c",300);
    Person p4("d",400);
    Person p5("e",500);
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);
    v.push_back(p4);
    v.push_back(p5);
    vector::iterator it = find(v.begin(),v.end(),p2);
    if(it != v.end())
    {
        cout << "Successfully to find ! Name is : " << (*it).name << " Age is : " << (*it).age;
    }
    else
    {
        cout << "Failed to find this!" << endl;
    }

}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
Successfully to find ! Name is : b Age is : 200
进程已结束,退出代码0

4.code3:find出现的问题

class Person
{
public:
    string name;
    int age;
    Person(string name,int age)
    {
        this -> name = name;
        this -> age = age;
    }
    void myprintPerson()
    {
        cout << "Name is : " << this->name << "  Age is : " << this->age << endl;
    }
    bool operator==(const Person & person)
    {
        return ((this->name == person.name)&&(this->age == person.age)) ;
    }
};

void test01()
{
    vectorv;
    Person p1("a",100);
    Person p2("b",200);
    Person p3("c",300);
    Person p4("d",400);
    Person p5("e",500);
    v.push_back(&p1);
    v.push_back(&p2);
    v.push_back(&p3);
    v.push_back(&p4);
    v.push_back(&p5);

    Person * p = new Person("b",200);

    vector::iterator it = find(v.begin(),v.end(),p);
    if(it != v.end())
    {
        cout << "Successfully to find ! Name is : " << (*it)->name << " Age is : " << (*it)->age;
    }
    else
    {
        cout << "Failed to find this!" << endl;
    }

}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
Failed to find this!

进程已结束,退出代码0

我们看到,这不符合我们的预期结果,这是为什么呢?我们将指向数据的指针传入了我们的容器,在find对比时,自然而然的是对比Person * 类型的数据是否一致,即编译器会比较地址是否一样,p的地址和p2明显不同(若回调函数改称&p2则返回成功),故达不到相同效果。另外,编译器内部有比较指针的函数,故调用不到我们写的回调函数。

5.code4:用find_if解决find发生的问题

class mycomp : public binary_function
{
public:
    bool operator()(const Person * p1,const Person * p2)const
    {
        return (p1->name == p2->name) && (p1->age == p2->age);
    }
};

void test02()
{
    vectorv;
    Person p1("a",100);
    Person p2("b",200);
    Person p3("c",300);
    Person p4("d",400);
    Person p5("e",500);
    v.push_back(&p1);
    v.push_back(&p2);
    v.push_back(&p3);
    v.push_back(&p4);
    v.push_back(&p5);

    Person * p = new Person("b",200);

    vector::iterator it = find_if(v.begin(),v.end(), bind2nd(mycomp(),p));
    if(it != v.end())
    {
        cout << "Successfully to find ! Name is : " << (*it)->name << " Age is : " << (*it)->age;
    }
    else
    {
        cout << "Failed to find this!" << endl;
    }

}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
Successfully to find ! Name is : b Age is : 200
进程已结束,退出代码0

6.adjacent_find的用法

7.code5:adjacent_find

void test03()
{
    vectorv;
    v.push_back(3);
    v.push_back(5);
    v.push_back(4);
    v.push_back(4);
    v.push_back(2);
    v.push_back(9);
    vector::iterator ret = adjacent_find(v.begin(),v.end());
    if(ret != v.end())
    {
        cout << "Find a adjcent complicate number : " << *ret << endl;
    }
    else
    {
        cout << "Fail to find !" << endl ;
    }
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
Find a adjcent complicate number : 4

进程已结束,退出代码0

8. binary_search的用法

9.count&count_if的用法

3.2.3 常用排序算法

1.二分查找的用法

 2.code1:二分查找

void test04()
{
    vectorv1;
    vectorv2;
    for(int i=0;i<10;i++)
    {
        v1.push_back(i);
        v2.push_back(i+2);
    }
    vectorTarget;
    Target.resize(v1.size()+v2.size());
    merge(v1.begin(),v1.end(),v2.begin(),v2.end(),Target.begin());
    for_each(Target.begin(),Target.end(),[](int val){cout << val << " ";});
}
home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
0 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 11 
进程已结束,退出代码0

3.sort查找的用法

4.random_shuffle算法:对指定范围内的元素随机调整顺序

void test05()
{
    vectorv;
    v.push_back(3);
    v.push_back(5);
    v.push_back(4);
    v.push_back(4);
    v.push_back(2);
    v.push_back(9);
    random_shuffle(v.begin(),v.end());
    for_each(v.begin(),v.end(),[](int val){cout << val << " ";});
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
2 4 5 4 3 9 
进程已结束,退出代码0

3.2.4 常用拷贝和替换算法

1.copy、replace、replace_if用法

2.code1:copy的简单实用

void test06()
{
    vectorv1;
    vectorv2;
    for(int i=0;i<10;i++)
    {
        v1.push_back(i);
    }
    v2.resize(v1.size());
    copy(v1.begin(),v1.end(),v2.begin());
    for_each(v2.begin(),v2.end(),[](int val){cout << val << " ";});
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
0 1 2 3 4 5 6 7 8 9 
进程已结束,退出代码0

3.code2:冲定位到流迭代器

需要引入头文件

void test06()
{
    vectorv1;
    vectorv2;
    for(int i=0;i<10;i++)
    {
        v1.push_back(i);
    }
    v2.resize(v1.size());
    copy(v1.begin(),v1.end(),v2.begin());
    copy(v2.begin(),v2.end(),ostream_iterator(cout," "));
}

用拷贝的算法向屏幕输出内容。

/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
0 1 2 3 4 5 6 7 8 9 
进程已结束,退出代码0

4.code3:replace

void test07()
{
    vectorv;
    v.push_back(3);
    v.push_back(5);
    v.push_back(4);
    v.push_back(4);
    v.push_back(2);
    v.push_back(9);
    replace(v.begin(),v.end(),4,1000);
    copy(v.begin(),v.end(),ostream_iterator(cout," "));
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
3 5 1000 1000 2 9 
进程已结束,退出代码0

5.code4:replace_if

class mycomif
{
public:
    int operator()(int val)
    {
        return val>3;
    }
};

void test07()
{
    vectorv;
    v.push_back(3);
    v.push_back(5);
    v.push_back(4);
    v.push_back(4);
    v.push_back(2);
    v.push_back(9);
    replace_if(v.begin(),v.end(),mycomif(),30000);
    copy(v.begin(),v.end(),ostream_iterator(cout," "));
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
3 30000 30000 30000 2 30000 
进程已结束,退出代码0

3.2.5 常用算术生成算法

1.生成算法简介

2.code1: accumulate

包含在头文件里

void test08()
{
    vectorv;
    for(int i = 1;i<=100;i++)
    {
        v.push_back(i);
    }
    int num = accumulate(v.begin(),v.end(),1000);
    cout << "num = " << num << endl;
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
num = 6050

进程已结束,退出代码0

1000 + 5050

3.code2:fill

void test09()
{
    vectorv;
    v.resize(10);
    fill(v.begin(),v.end(),1000);
    copy(v.begin(),v.end(),ostream_iterator(cout," "));
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 
进程已结束,退出代码0

3.2.6 常用集合算法

1.交集并集算法简介

2.差集算法简介

3.code1:交集

void test10()
{
    vectorv1;
    vectorv2;
    for(int i=0;i<10;i++)
    {
        v1.push_back(i);
        v2.push_back(i+2);
    }
    vector Target;
    Target.resize(min(v1.size(),v2.size()));
    vector::iterator end = set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),Target.begin());
    for_each(Target.begin(),end,[](int val){cout << val << " ";});
}
/home/liuhongwei/桌面/slam/stlday3/cmake-build-debug/stlday3
2 3 4 5 6 7 8 9 
进程已结束,退出代码0

xx

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/982466.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号