• STL学习笔记(随缘更新)


    vector容器

    vector基本概念

    功能:

    • vector数据结构和数组非常相似,也称为单端数组

    vector与普通数组区别:

    • 不同之处在于数组是静态空间,而vector可以动态扩展

    动态扩展:

    • 并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间

    • vector容器的迭代器是支持随机访问的迭代器

    vector构造函数

    功能描述:

    • 创建vector容器

    函数原型:

    • vector v; //采用模板实现类实现,默认构造函数
    • vector(v.begin(), v.end()); //将v[begin(), end())区间中的元素拷贝给本身。
    • vector(n, elem); //构造函数将n个elem拷贝给本身。
    • vector(const vector &vec); //拷贝构造函数。

    示例:

    #include 
    
    void printVector(vector<int>& v) {
    
    	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
    		cout << *it << " ";
    	}
    	cout << endl;
    }
    
    void test01()
    {
    	vector<int> v1; //无参构造
    	for (int i = 0; i < 10; i++)
    	{
    		v1.push_back(i);
    	}
    	printVector(v1);
    
    	vector<int> v2(v1.begin(), v1.end());
    	printVector(v2);
    
    	vector<int> v3(10, 100);
    	printVector(v3);
    	
    	vector<int> v4(v3);
    	printVector(v4);
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    总结:vector的多种构造方式没有可比性,灵活使用即可

    vector赋值操作

    功能描述:

    • 给vector容器进行赋值

    函数原型:

    • vector& operator=(const vector &vec);//重载等号操作符

    • assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。

    • assign(n, elem); //将n个elem拷贝赋值给本身。

    示例:

    #include 
    
    void printVector(vector<int>& v) {
    
    	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
    		cout << *it << " ";
    	}
    	cout << endl;
    }
    
    //赋值操作
    void test01()
    {
    	vector<int> v1; //无参构造
    	for (int i = 0; i < 10; i++)
    	{
    		v1.push_back(i);
    	}
    	printVector(v1);
    
    	vector<int>v2;
    	v2 = v1;
    	printVector(v2);
    
    	vector<int>v3;
    	v3.assign(v1.begin(), v1.end());
    	printVector(v3);
    
    	vector<int>v4;
    	v4.assign(10, 100);
    	printVector(v4);
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    总结: vector赋值方式比较简单,使用operator=,或者assign都可以

    vector容量和大小

    功能描述:

    • 对vector容器的容量和大小操作

    函数原型:

    • empty(); //判断容器是否为空

    • capacity(); //容器的容量

    • size(); //返回容器中元素的个数

    • resize(int num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。

    • resize(int num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除

    示例:

    #include 
    
    void printVector(vector<int>& v) {
    
    	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
    		cout << *it << " ";
    	}
    	cout << endl;
    }
    
    void test01()
    {
    	vector<int> v1;
    	for (int i = 0; i < 10; i++)
    	{
    		v1.push_back(i);
    	}
    	printVector(v1);
    	if (v1.empty())
    	{
    		cout << "v1为空" << endl;
    	}
    	else
    	{
    		cout << "v1不为空" << endl;
    		cout << "v1的容量 = " << v1.capacity() << endl;
    		cout << "v1的大小 = " << v1.size() << endl;
    	}
    
    	//resize 重新指定大小 ,若指定的更大,默认用0填充新位置,可以利用重载版本替换默认填充
    	v1.resize(15,10);
    	printVector(v1);
    
    	//resize 重新指定大小 ,若指定的更小,超出部分元素被删除
    	v1.resize(5);
    	printVector(v1);
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    总结:

    • 判断是否为空 — empty
    • 返回元素个数 — size
    • 返回容器容量 — capacity
    • 重新指定大小 — resize

    vector插入和删除

    功能描述:

    • 对vector容器进行插入、删除操作

    函数原型:

    • push_back(ele); //尾部插入元素ele
    • pop_back(); //删除最后一个元素
    • insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele
    • insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele
    • erase(const_iterator pos); //删除迭代器指向的元素
    • erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素
    • clear(); //删除容器中所有元素

    示例:

    
    #include 
    
    void printVector(vector<int>& v) {
    
    	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
    		cout << *it << " ";
    	}
    	cout << endl;
    }
    
    //插入和删除
    void test01()
    {
    	vector<int> v1;
    	//尾插
    	v1.push_back(10);
    	v1.push_back(20);
    	v1.push_back(30);
    	v1.push_back(40);
    	v1.push_back(50);
    	printVector(v1);
    	//尾删
    	v1.pop_back();
    	printVector(v1);
    	//插入
    	v1.insert(v1.begin(), 100);
    	printVector(v1);
    
    	v1.insert(v1.begin(), 2, 1000);
    	printVector(v1);
    
    	//删除
    	v1.erase(v1.begin());
    	printVector(v1);
    
    	//清空
    	v1.erase(v1.begin(), v1.end());
    	v1.clear();
    	printVector(v1);
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    总结:

    • 尾插 — push_back
    • 尾删 — pop_back
    • 插入 — insert (位置迭代器)
    • 删除 — erase (位置迭代器)
    • 清空 — clear

    vector数据存取

    功能描述:

    • 对vector中的数据的存取操作

    函数原型:

    • at(int idx); //返回索引idx所指的数据
    • operator[]; //返回索引idx所指的数据
    • front(); //返回容器中第一个数据元素
    • back(); //返回容器中最后一个数据元素

    示例:

    #include 
    
    void test01()
    {
    	vector<int>v1;
    	for (int i = 0; i < 10; i++)
    	{
    		v1.push_back(i);
    	}
    
    	for (int i = 0; i < v1.size(); i++)
    	{
    		cout << v1[i] << " ";
    	}
    	cout << endl;
    
    	for (int i = 0; i < v1.size(); i++)
    	{
    		cout << v1.at(i) << " ";
    	}
    	cout << endl;
    
    	cout << "v1的第一个元素为: " << v1.front() << endl;
    	cout << "v1的最后一个元素为: " << v1.back() << endl;
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    总结:

    • 除了用迭代器获取vector容器中元素,[ ]和at也可以
    • front返回容器第一个元素
    • back返回容器最后一个元素

    vector互换容器

    功能描述:

    • 实现两个容器内元素进行互换

    函数原型:

    • swap(vec); // 将vec与本身的元素互换

    示例:

    #include 
    
    void printVector(vector<int>& v) {
    
    	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
    		cout << *it << " ";
    	}
    	cout << endl;
    }
    
    void test01()
    {
    	vector<int>v1;
    	for (int i = 0; i < 10; i++)
    	{
    		v1.push_back(i);
    	}
    	printVector(v1);
    
    	vector<int>v2;
    	for (int i = 10; i > 0; i--)
    	{
    		v2.push_back(i);
    	}
    	printVector(v2);
    
    	//互换容器
    	cout << "互换后" << endl;
    	v1.swap(v2);
    	printVector(v1);
    	printVector(v2);
    }
    
    void test02()
    {
    	vector<int> v;
    	for (int i = 0; i < 100000; i++) {
    		v.push_back(i);
    	}
    
    	cout << "v的容量为:" << v.capacity() << endl;
    	cout << "v的大小为:" << v.size() << endl;
    
    	v.resize(3);
    
    	cout << "v的容量为:" << v.capacity() << endl;
    	cout << "v的大小为:" << v.size() << endl;
    
    	//收缩内存
    	vector<int>(v).swap(v); //匿名对象
    
    	cout << "v的容量为:" << v.capacity() << endl;
    	cout << "v的大小为:" << v.size() << endl;
    }
    
    int main() {
    
    	test01();
    
    	test02();
    
    	system("pause");
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    总结:swap可以使两个容器互换,可以达到实用的收缩内存效果

    vector预留空间

    功能描述:

    • 减少vector在动态扩展容量时的扩展次数

    函数原型:

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

    示例:

    #include 
    
    void test01()
    {
    	vector<int> v;
    
    	//预留空间
    	v.reserve(100000);
    
    	int num = 0;
    	int* p = NULL;
    	for (int i = 0; i < 100000; i++) {
    		v.push_back(i);
    		if (p != &v[0]) {
    			p = &v[0];
    			num++;
    		}
    	}
    
    	cout << "num:" << num << endl;
    }
    
    int main() {
    
    	test01();
        
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    总结:如果数据量较大,可以一开始利用reserve预留空间

    stack

    stack 基本概念

    概念
    stack是一种先进后出(First In Last Out,FILO)的数据结构,它只有一个出口。
    stack的一些特点:

    • 栈不允许有遍历的行为
    • 栈可以判断容器是否为空
    • 栈可以返回元素的个数(size在入栈的时候可以进行统计)
      在这里插入图片描述

    栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为

    栈中进入数据称为 — 入栈 push

    栈中弹出数据称为 — 出栈 pop

    stack常用接口

    功能描述:栈容器常用的对外接口

    构造函数:

    • stack stk; //stack采用模板类实现, stack对象的默认构造形式
    • stack(const stack &stk); //拷贝构造函数

    赋值操作:

    • stack& operator=(const stack &stk); //重载等号操作符

    数据存取:

    • push(elem); //向栈顶添加元素
    • pop(); //从栈顶移除第一个元素
    • top(); //返回栈顶元素

    大小操作:

    • empty(); //判断堆栈是否为空
    • size(); //返回栈的大小

    queue

    queue基本概念

    其实栈和队列都是可以由链表改造过来的。原理基本与栈一样。
    概念:Queue是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口。
    在这里插入图片描述
    队列容器只允许从一端新增元素,从另一端移除元素(参考现在做的核酸检测排队

    队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为

    队列中进数据称为 — 入队 push

    队列中出数据称为 — 出队 pop

    queue 常用接口

    功能描述:栈容器常用的对外接口

    构造函数:

    • queue que; //queue采用模板类实现,queue对象的默认构造形式
    • queue(const queue &que); //拷贝构造函数

    赋值操作:

    • queue& operator=(const queue &que); //重载等号操作符

    数据存取:

    • push(elem); //往队尾添加元素
    • pop(); //从队头移除第一个元素
    • back(); //返回最后一个元素
    • front(); //返回第一个元素

    大小操作:

    • empty(); //判断堆栈是否为空
    • size(); //返回栈的大小

    总结:

    • 入队 — push
    • 出队 — pop
    • 返回队头元素 — front
    • 返回队尾元素 — back
    • 判断队是否为空 — empty
    • 返回队列大小 — size

    list

    list基本概念

    **功能:**将数据进行链式存储

    链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的

    链表的组成:链表由一系列结点组成

    结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

    STL中的链表是一个双向循环链表(有两个指针分别指向前驱和后继,且最后一个节点记录的是第一个有效节点的位置,第一个有效节点的前一个节点记录的是最后一个节点的位置)
    在这里插入图片描述
    由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器

    list的优点:

    • 采用动态存储分配,不会造成内存浪费和溢出
    • 链表执行插入和删除操作十分方便(任意位置),修改指针即可,不需要移动大量元素

    list的缺点:

    • 链表灵活,但是空间(指针域) 和 时间(遍历)额外耗费较大。
    • 不能利用[ ]以及at的方式访问数据,与底层结构有关,因为底层是链表,非一段连续的内存,其迭代器是双向迭代器,只支持前移后移,不支持随机访问&跳跃访问。

    List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。

    总结:STL中List和vector是两个最常被使用的容器,各有优缺点

    list构造函数

    功能描述:

    • 创建list容器

    函数原型:

    • list lst; //list采用采用模板类实现,对象的默认构造形式:
    • list(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身。
    • list(n,elem); //构造函数将n个elem拷贝给本身。
    • list(const list &lst); //拷贝构造函数。

    总结:list构造方式同其他几个STL常用容器,熟练掌握即可

    list 赋值和交换

    功能描述:

    • 给list容器进行赋值,以及交换list容器

    函数原型:

    • assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。
    • assign(n, elem); //将n个elem拷贝赋值给本身。
    • list& operator=(const list &lst); //重载等号操作符
    • swap(lst); //将lst与本身的元素互换。

    list 大小操作

    功能描述:

    • 对list容器的大小进行操作

    函数原型:

    • size(); //返回容器中元素的个数

    • empty(); //判断容器是否为空

    • resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。

    • resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。

    list 插入和删除

    功能描述:

    • 对list容器进行数据的插入和删除

    函数原型:

    • push_back(elem);//在容器尾部加入一个元素
    • pop_back();//删除容器中最后一个元素
    • push_front(elem);//在容器开头插入一个元素
    • pop_front();//从容器开头移除第一个元素
    • insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
    • insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
    • insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
    • clear();//移除容器的所有数据
    • erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
    • erase(pos);//删除pos位置的数据,返回下一个数据的位置。
    • remove(elem);//删除容器中所有与elem值匹配的元素。

    在erease与insert当中,都是需要提供迭代器的,迭代器可以与运算符相结合(++,- - 之类的)

    总结:

    • 尾插 — push_back
    • 尾删 — pop_back
    • 头插 — push_front
    • 头删 — pop_front
    • 插入 — insert
    • 删除 — erase
    • 移除 — remove
    • 清空 — clear

    list 数据存取

    功能描述:

    • 对list容器中数据进行存取

    函数原型:

    • front(); //返回第一个元素。
    • back(); //返回最后一个元素。
    	//list容器的迭代器是双向迭代器,不支持随机访问
    	list<int>::iterator it = L1.begin();
    	it = it + 1;//错误,不可以跳跃访问,即使是+1
    	it++;//正确,前移
    	it--;//正确,后移
    
    • 1
    • 2
    • 3
    • 4
    • 5

    总结:

    • list容器中不可以通过[ ]或者at方式访问数据
    • 返回第一个元素 — front
    • 返回最后一个元素 — back

    list 反转和排序

    功能描述:

    • 将容器中的元素反转,以及将容器中的数据进行排序

    函数原型:

    • reverse(); //反转链表
    • sort(); //链表排序

    使用sort的时候需要注意,首先要包含algorithm的头文件,其次,所有不支持随机访问迭代器的容器,不可以使用标准算法。所以,不支持随机访问迭代器的容器,内部会提供一些算法

    	//排序
    	L.sort(); //默认的排序规则 从小到大
    	printList(L);
    	sort(L1.begin(), L1.end());//这个就是错误的,因为标准算法只支持随机访问的迭代器容器
    
    • 1
    • 2
    • 3
    • 4

    高级排序

    加入仿函数的规则。例如此题:排序规则,按照年龄进行升序,如果年龄相同按照身高进行降序。

    bool ComparePerson(Person& p1, Person& p2) {
    
    	if (p1.m_Age == p2.m_Age) {
    		return p1.m_Height  > p2.m_Height;
    	}
    	else
    	{
    		return  p1.m_Age < p2.m_Age;
    	}
    }
    
    //
    
    L.sort(ComparePerson);//把仿函数的名字加进去就行
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    set / multiset 容器

    set基本概念

    简介:

    • 所有元素都会在插入时自动被排序(关联式容器)

    本质:

    • set/multiset属于关联式容器,底层结构是用二叉树实现。

    set和multiset区别

    • set不允许容器中有重复的元素
    • multiset允许容器中有重复的元素
    • 综上就是一个可以放重复的一个不可以放,头文件都是set

    set构造和赋值

    功能描述:创建set容器以及赋值

    构造:

    • set st; //默认构造函数:
    • set(const set &st); //拷贝构造函数

    赋值:

    • set& operator=(const set &st); //重载等号操作符

    PS:
    set容器在插入中,只有insert的方式,没有oush,pop的方式。

    set大小和交换

    功能描述:

    • 统计set容器大小以及交换set容器

    函数原型:

    • size(); //返回容器中元素的数目
    • empty(); //判断容器是否为空
    • swap(st); //交换两个集合容器

    set插入和删除

    功能描述:

    • set容器进行插入数据和删除数据

    函数原型:

    • insert(elem); //在容器中插入元素。
    • clear(); //清除所有元素
    • erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
    • erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
    • erase(elem); //删除容器中值为elem的元素。

    set查找和统计

    功能描述:

    • 对set容器进行查找数据以及统计数据

    函数原型:

    • find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
    • count(key); //统计key的元素个数

    set和multiset区别

    学习目标:

    • 掌握set和multiset的区别

    区别:

    • set不可以插入重复数据,而multiset可以
    • set插入数据的同时会返回插入结果,表示插入是否成功,用pair来表示
    • multiset不会检测数据,因此可以插入重复数据

    pair对组创建

    功能描述:

    • 成对出现的数据,利用对组可以返回两个数据

    两种创建方式:

    • pair p ( value1, value2 );
    • pair p = make_pair( value1, value2 );
      value1与value2是给这个默认构造赋两个基本的值。这两个数据调用的时候,第一个叫first,第二个叫secend。
      示例:
    #include 
    #include 
    using namespace std;
    #include 
    
    //对组创建
    void test01()
    {
    	pair<string, int> p(string("Tom"), 20);
    	cout << "姓名: " <<  p.first << " 年龄: " << p.second << endl;
    
    	pair<string, int> p2 = make_pair("Jerry", 10);
    	cout << "姓名: " << p2.first << " 年龄: " << p2.second << endl;
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    总结:

    两种方式都可以创建对组,记住一种即可

    set容器排序

    学习目标:

    • set容器默认排序规则为从小到大,掌握如何改变排序规则

    主要技术点:

    • 利用仿函数,可以改变排序规则
    • 仿函数,本身是一个类型
    #include 
    #include 
    using namespace std;
    
    class MyCompare 
    {
    public:
    	bool operator()(int v1, int v2) {
    		return v1 > v2;
    	}
    };
    
    void test01() 
    {    
    	set<int> s1;
    	s1.insert(10);
    	s1.insert(40);
    	s1.insert(20);
    	s1.insert(30);
    	s1.insert(50);
    
    	//默认从小到大
    	for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
    		cout << *it << " ";
    	}
    	cout << endl;
    
    	//指定排序规则
    	//按照仿函数的规则进行插入
    	set<int,MyCompare> s2;
    	s2.insert(10);
    	s2.insert(40);
    	s2.insert(20);
    	s2.insert(30);
    	s2.insert(50);
    
    	for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {
    		cout << *it << " ";
    	}
    	cout << endl;
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    关于bool operator()(int v1, int v2)当中的两个括号的解释,第一个括号表示的是需要重载的符号,第二个括号表示重载符号函数体的参数列表。

    仿函数定义以及重载( )

    仿函数(functor),就是使一个类的使用看上去象一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。

    #include   
    using namespace std;  
    class Time  
    {  
    public:  
        //小括号重载 版本0 
        void operator()()  
        {  
            cout<< "version 0"<<endl;  
        }  
        //小括号重载 版本1  
    	void operator()(int h)  
        {  
            cout<< "version 1"<<endl;  
        }  
        //小括号重载 版本2  
    	void operator()(int h, int m)  
        {  
            cout<< "version 2"<<endl;  
        }  
    };  
      
    int main()  
    {  
        Time t;  
    	t();
        t(1);                    //小括号重载 版本1  
        t(1,1);                  //小括号重载 版本2  
        return 0;  
    }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    set存放自定义数据类型

    直接举例,按照年龄顺序降序排列。

    #include 
    #include 
    #include 
    
    using namespace std;
    
    class Person
    {
    public:
        Person(string name, int age)
        {
            this->m_Name = name;
            this->m_Age = age;
        }
        string m_Name;
        int m_Age;
    };
    
    class comparePerson
    {
    public:
        bool operator()(const Person& p1, const Person& p2)
        {
            //按照年龄做降序
            return p1.m_Age > p2.m_Age;
        }
    };
    
    void test01()
    {
        set<Person,comparePerson>s;
        //创建Person对象
        Person p1("刘备", 23);
    	Person p2("关羽", 27);
    	Person p3("张飞", 25);
    	Person p4("赵云", 21);
    
    	s.insert(p1);
    	s.insert(p2);
    	s.insert(p3);
    	s.insert(p4);
    
        for (set<Person, comparePerson>::iterator it = s.begin(); it!= s.end(); ++it)
        {
            cout << "姓名:" << (*it).m_Name << "年龄:" << (*it).m_Age << endl;
        }
    }
    
    int main()
    {
        test01();
        system("pause");
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    map/ multimap容器

    map基本概念

    简介:

    • map中所有元素都是pair(两个两个一起出现)
    • pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
    • 所有元素都会根据元素的键值自动排序

    本质:

    • map/multimap属于关联式容器,底层结构是用二叉树实现。

    优点:

    • 可以根据key值快速找到value值

    map和multimap区别

    • map不允许容器中有重复key值元素
    • multimap允许容器中有重复key值元素

    map构造和赋值

    功能描述:

    • 对map容器进行构造和赋值操作

    函数原型:

    构造:

    • map mp; //map默认构造函数:
    • map(const map &mp); //拷贝构造函数

    赋值:

    • map& operator=(const map &mp); //重载等号操作符

    在向map当中插入值得时候,记住一定要插入一个pair,因为map的基本就是pair组成的。

    map大小和交换

    功能描述:

    • 统计map容器大小以及交换map容器

    函数原型:

    • size(); //返回容器中元素的数目
    • empty(); //判断容器是否为空
    • swap(st); //交换两个集合容器

    map插入和删除

    功能描述:

    • map容器进行插入数据和删除数据

    函数原型:

    • insert(elem); //在容器中插入元素。
    • clear(); //清除所有元素
    • erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
    • erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
    • erase(key); //删除容器中值为key的元素。
    #include 
    
    void printMap(map<int,int>&m)
    {
    	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
    	{
    		cout << "key = " << it->first << " value = " << it->second << endl;
    	}
    	cout << endl;
    }
    
    void test01()
    {
    	//插入
    	map<int, int> m;
    	//第一种插入方式
    	m.insert(pair<int, int>(1, 10));
    	//第二种插入方式
    	m.insert(make_pair(2, 20));
    	//第三种插入方式
    	m.insert(map<int, int>::value_type(3, 30));
    	//第四种插入方式
    	m[4] = 40; //不建议用此方法
    	printMap(m);
    
    	//删除
    	m.erase(m.begin());
    	printMap(m);
    
    	m.erase(3);//按照key删除
    	printMap(m);
    
    	//清空
    	m.erase(m.begin(),m.end());
    	m.clear();
    	printMap(m);
    }
    
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    不建议[ ]进行插入操作,但可以用于key访问value。

    总结:

    • map插入方式很多,记住其一即可
    • 插入 — insert
    • 删除 — erase
    • 清空 — clear

    map查找和统计

    功能描述:
    按照key的方式去查找/统计,对map而言无非就是0/1。

    • 对map容器进行查找数据以及统计数据

    函数原型:

    • find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
    • count(key); //统计key的元素个数

    map容器排序

    学习目标:

    • map容器默认排序规则为,按照key值进行从小到大排序,掌握如何改变排序规则

    主要技术点:

    • 利用仿函数,可以改变排序规则

    示例:

    #include 
    
    class MyCompare {
    public:
    	bool operator()(int v1, int v2) {
    		return v1 > v2;
    	}
    };
    
    void test01() 
    {
    	//默认从小到大排序
    	//利用仿函数实现从大到小排序
    	map<int, int, MyCompare> m;
    
    	m.insert(make_pair(1, 10));
    	m.insert(make_pair(2, 20));
    	m.insert(make_pair(3, 30));
    	m.insert(make_pair(4, 40));
    	m.insert(make_pair(5, 50));
    
    	for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
    		cout << "key:" << it->first << " value:" << it->second << endl;
    	}
    }
    int main() {
    
    	test01();
    
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    总结:

    • 利用仿函数可以指定map容器的排序规则
    • 对于自定义数据类型,map必须要指定排序规则,同set容器
  • 相关阅读:
    被誉为“芯片之母”,中国团队拿下EDA全球冠军,平均年龄24岁
    我的测试文章
    浅谈基于云计算的环境智能监控系统
    Pickle反序列化学习
    青海、山西二建成绩公布 安徽二建有25033人合格进行公示
    Unity-CharacterController(角色控制器)
    车辆工程的入门学习
    mysqlMHA高可用
    leetcode做题笔记217. 存在重复元素
    JavaScript面向对象:面向过程与面向对象
  • 原文地址:https://blog.csdn.net/weixin_44673253/article/details/125904539