c++知识点总结--STL

STL介绍

STL Standard template library ------标准模板库
STL广义划分为: 容器container; 算法algorithm; 迭代器iterator
容器和算法之间通过迭代器进行无缝衔接。
STL几乎所有代码都采用了模板类或者模板函数;
STL分为六大组件:容器,算法,迭代器,仿函数,适配器,空间配置器
容器:各种数据结构:vector,list,deque,set,map;
算法:各种常见算法:sort,find,copy,for_each;
迭代器:扮演容器和算法之间的胶合剂;
仿函数:行为类似函数,可作为算法的某种策略;
//适配器:一直用来修饰容器或者仿函数或迭代器接口的东西;
//空间配置器:负责空间的配置和管理;
STL具有容器概念和容器类型,容器概念是具有名称的(容器,序列容器,关联容器等)的通用类型;容器类型是可以用于创建具体容器对象的模板(deque,list,queue,priority_queue,stack,vector,map,multimap,set,multiset(关联容器),bitset);以及c++新添加的forward_list,unordered_map,unordered_multimap,unordered_set,unordered_multiset.

容器
是存储其他对象的对象。被存储的对象必须是同一种类型的。但也不能将任何类型的对象存储在容器中,具体讲:类型必须是可复制构造和可赋值的。基本数据满足这些要求,当没有将复制构造函数和赋值构造函数声明为私有或保护,就可以满足。

序列容器
强调值的顺序,每个元素都有固定的位置;

关联容器
二叉树结构,各个元素没有严格意义上的顺序关系;
----map,multimap,set,multiset
set 的值类型和键相同,这意味着集合中不会有多个相同的键。multisetset类似,但是可能有多个值的键相同。
map的值和键类型不同,键是惟一的,每个键只对应一个值,同理,multimapmap类似,但可以一个键与多个值关联。

仿函数—函数对象—函数符
可以函数方式与()结合使用容易对象。包括了函数名,指向函数的指针和重载()运算符的类对象

迭代器

  1. 背景:指针可以用来遍历存储空间连续的数据结构,但是对于存储空间非连续的,就需要寻找一个行为类似指针的类,来对非数组的数据结构进行遍历。
    定义:迭代器是一种检查容器内元素并遍历元素的数据类型。
    迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。
    迭代器(iterator)是指针(pointer)的泛化,它允许程序员用相同的方式处理不同的数据结构(容器)。
    (1)迭代器类似于C语言里面的指针类型,它提供了对对象的间接访问。
    (2)指针是C语言中的知识点,迭代器是C++中的知识点。指针较灵活,迭代器功能较丰富。
    (3)迭代器提供一个对容器对象的访问方法,并定义了容器范围。
  2. 迭代器和指针的区别:
    容器有迭代器类型同时拥有返回迭代器的成员。如:容器有成员begin和end,其中begin成员复制返回指向第一个元素的迭代器,而end成员返回指向容器尾元素的下一个位置的迭代器,也就是说end指示的是一个不存在的元素,所以end返回的是尾后迭代器。可以通过迭代器访问容器中的元素。
//example
 vetor<int> v(10,1);
 vector<int>::iterator first = v.begin();
 vector<int>::iterator second = v.begin()+1;
 *(first+1) == *second; //true ,指向同一个
  1. 容器迭代器的使用
    每种容器类型都定义了自己的迭代器类型,简单说就是容器类定义了自己的iterator类型,用于访问容器内的元素。每个容器定义了一种名为iterator的类型,这种类型支持迭代器的各种行为。

常见容器:

容器类型迭代器类型
vector随机
deque随机
list双向
set双向
multiset双向
map双向
multimap双向
迭代器操作双向随机
it++/++it/it–/–it支持支持
it[n]不支持支持
it+n / it-n不支持支持
it+=n / it-=n不支持支持
*it支持支持

map虽然也支持[],但是[]内部是键,得到的是值。string也支持[]

1、array

	array<int, 35> arr{3};//一个3,其他为0;
	array<int, 35> ar;//35个不确定的值;{} 全为0
	//arr.assign(5);
	int b1 = arr.at(12);//返回容器中 n(12) 位置处元素的引用,该函数自动检查 n(12)是否在有效的范围内,如果不是则抛出 out_of_range 异常。
	int b2 = arr.back();//返回容器中最后一个元素的直接引用,该函数同样不适用于空的 array 容器。
	arr.begin();//返回指向容器中第一个元素的随机访问迭代器。
	arr.cbegin();//和 begin() 功能相同,只不过在其基础上增加了 const 属性,不能用于修改元素。
	arr.cend();
	arr.crbegin();
	arr.crend();
	auto b3 = arr.data();//返回一个指向容器首个元素的指针。利用该指针,可实现复制容器中所有元素等类似功能。
	arr.empty();
	arr.end();//返回指向容器最后一个元素之后一个位置的随机访问迭代器,通常和 begin() 结合使用。
	arr.fill(2);//将 val(2) 这个值赋值给容器中的每个元素。
	int b5 = arr.front();//返回容器中第一个元素的直接引用,该函数不适用于空的 array 容器。
	arr.max_size();// 返回容器可容纳元素的最大数量,其值始终等于初始化 array 类的第二个模板参数 N。
	arr[1];
	arr.rbegin();//返回指向最后一个元素的随机访问迭代器。
	arr.rend();//返回指向第一个元素之前一个位置的随机访问迭代器。
	arr.size();
	arr.swap(ar);//交换 array1 和 array2 容器中的所有元素,但前提是它们具有相同的长度和类型。

2、vector

//vector
//初始化方法
	vector<int> v1;
	vector<int> v2(10,1);
	vector<int> v3(v2.begin(),v2.begin()+3);
	vector<int> v5{1,2,3,4,5};
//其他
	v2.assign(2,6); //重新分配,2个6
	v2.at(1); //等价与v2[1]
	v2.back();//返回v2的最后一个元素
	v2.begin();//返回v2的开始迭代器
	v2.capacity();//返回容量---容量的意思是,当容器中元素个数大于容量时,会自动进行扩容。
	v2,cbegin();
	v2.cend();
	v2.clear();//清除v2所有元素
	v2.crbegin();
	v2.crend();
	auto *p =v2.data();//返回一个指针指向容器第一个元素所在的内存。
	v2.emplace(v2.begin(),1);
	v2.emplace_back(2);//尾部插入
	v2.empty();//判断是否为空
	v2.end();//v2的尾迭代器,指向最后一个元素的后面一个
	v2.erase(v2.begin());//删除迭代器指向元素
	v2.erase(v2.begin()+1,v2.begin()+3);//删除迭代器区间元素[a,b)
	v2.front();//返回第一个元素
	//v2.get_allocator();
	v2.insert(v2.begin(),3);//在指定位置插入指定元素
	v2.max_size();//返回最大可能的容器大小
	vector<int> v4 = v2;
	v2[1];
	v2.pop_back();//删除最后一个元素
	v2.push_back(11);//在末尾添加指定元素
	v2.rbegin();//返回的是一个反向的随机访问迭代器。指向最后一个元素的迭代器,即 v2.rbegin()+1 ---指向倒数第二个元素的迭代器
	v2.rend();//返回的是一个反向的随机访问迭代器。指向第一个元素前一个位置的迭代器,即 v2.rbegin()-3 ---指向第三个元素的迭代器
	v2.reserve(20);//容器预留len个元素长度,预留位置不初始化,元素不可访问。在调用默认构造函数后,就使用。
	v2.resize(11);//重新制定容器长度为num。若容器长度变长,则以默认值0填充新位置,若变短,删除超出元素。
	v2.resize(19,99);//若变长,以99填充
	v2.shrink_to_fit();//收缩到合适大小
	v2.size();//返回容器大小
	v2.swap(v1);//互换

3、string

//string
//初始化方法
	string s1("abcd");
	char c[] = "bcd";
	string s2(c);
	string s3(c,2);//c的前两个字符
	string s3(s1);
	string s33(s1.begin(),s1.end());
	string s4(5,'a');
//其他
	string s = "abcdefabcdef";
	s.append("gh");//s后面追加dsdd
	s.assign("abcdefabcdef");
	s += "sdd";
	cout << s << endl;
	s.at(1);
	s[1];
	s.back();//返回最后一个元素
	s.begin();
	s.c_str();//返回char *
	s.capacity();
	s.clear();
	s.compare("abc");//比较大小,s大返回值大于0,s小返回值小于0,相等返回0
	s.copy(c,3,2);//将s的第2个位置开始的3个元素copy给c的开始3个位置上,若c的这些位置有元素,则覆盖。
	s.cbegin();
	s.cend();
	s.crbegin();
	s.crend();
	s.data();//Return const pointer to contents. This is a handle to internal data. Do not modify or dire things may happen.即返回s最开始元素的地址;注意不等于s的地址,是索引0的地址
	s.empty();
	s.end();
	s.erase(s.begin());
	s.erase(s.begin(),s.begin()+1);
	s.find('s',0);
	s.find("bcdef",0,4);//从s的0索引开始,寻到“bcdef”的前四个组成的子串;找到返回子串的首字符索引,否则,返回npos。
	s.find_first_not_of("mn",2);//从 pos=2开始,在此字符串中查找不包含在"mn"中的字符首次出现的位置。如果未找到,则返回npos。
	s.find_first_of("def",1);//从pos开始,在s中查找"def"中任何一个字符首次出现的位置
	s.find_last_not_of("defs",2);//从pos开始,在此字符串中查找不包含在"defs"中的字符最后一次出现的位置。
	s.find_last_of("de",1);//从pos开始,在s中查找"de"中任何一个字符最后一次出现的位置。
	s.front();
	//s.get_allocator();
	s.insert(3,"s");//在s的索引3处插入s
	s.insert(2,5,'s');//在s的索引2插入5个s
	s.insert(2,s1);//在s的索引2插入s1
	s.length();//返回字符串中的字符数
	s.max_size();//返回最大可能的容器大小
	s.npos;//18446744073709551615UL,一般在函数失败,返回该值,最大允许长度
	//++,=,[]
	s.pop_back();
	s.push_back('s');
	s.rbegin();//返回指向字符串的最后一个字符。迭代是在反向元素中完成的命令
	s.rend();//返回指向字符串中的第一个字符前一个位置。迭代是反向进行的元素顺序。
	s.replace(1,2,"aaa");//替换从s的索引1开始的两个元素为aaa,相当于删除索引1开始的2个元素,然后在索引1处插入aaa
	s.reserve(100);//尝试为指定数量的字符预先分配足够的内存,与容量挂钩
	s.resize(10);
	s.rfind("cd",8);//从索引0开始到8结束,向后搜索此字符串。如果找到,则返回字符串索引0的元素在s中对应子串最后一次结果的索引。即在s中找到cd的话,返回最后一次结果的字母c在s中的索引,不写后面的8,就是在整个s上搜索
	s.shrink_to_fit();//收缩大小到合适
	s.size();
	s.substr(1,3);//返回子串从索引1开始的3个,
	s.swap(s1);//交换两者内容

4、deque

//deque 双端数组
//初始化方法
		deque<int> deq1;
		deque<int> deq2(5,2);
		deque<int> deq3(deq2.begin(),deq2.begin()+3);
		deque<int> deq4(deq2);
//其他
		deque<int> deq(10,1);
		deq.assign(9,2);//相当于=,赋值
		deq.at(1);
		deq.back();//返回最后一个元素值
		deq.begin();//返回第一个元素的迭代器
		deq.clear();//删除所有元素
		deq.empty();//判断是否为空
		deq.end();
		deq.erase(deq.begin());
		deq.erase(deq.begin(),deq.begin()+2);
		deq.front();//返回第一个元素
		deq.insert(deq.begin(),3);
		deq.insert(deq.begin(),3,5);//在指定迭代器出插入3个5;
		deq.insert(deq.begin(),deq2.begin(),deq2.begin()+3);//在指定迭代器位置插入deq2的前3个元素;
		deq.max_size();//返回容器容量
		deq.pop_back();//删除最后一个元素
		deq.pop_front();//删除第一个元素
		deq.push_back(3);//在尾部添加元素3
		deq.push_front(1);//在头部添加元素1
		deq.rbegin();//指向最后一个元素的迭代器,方向从后往前
		deq.rend();//指向第一个元素的前一个位置的迭代器,方向从后往前
		deq.resize(7);//重定size,大于原来的补0,多了删尾;
		deq.size();
		deq.swap(deq2);//交换
		deq=deq2;
		deq[2];

5、queue

//queue
//初始化方法
	queue<int> que1;
	queue<int> que2(que1);
//其他
	que1.back();//返回队列的最后一个元素,前提非空
	que1.emplace(1);//类似于push,但是也有细微区别。
	que1.empty();//判断队列是否为空
	que1.front();//返回队列最前面的元素
	que1.pop();//弹出队列最前面的元素
	que1.push(1);//向队列末尾加入元素
	que1.size();//队列大小
	que1.swap(que2);//交换两个队列

6、priority_queue

//优先队列默认从大到小
//包含在queue中,没有priority_queue头文件
	priority_queue<int,vector<int>,std::greater<int>> p;//从小到大
	//第一个int是数据类型,第二个vector<int>是实现类型,第三个是优先级,less<int>实现从大到小(默认)
	//这里的从大到小或者是从小到大,是出队列的顺序。
	priority_queue<int> pd(2, 1);
	priority_queue<int> pdd(pd);
	pd.emplace(3);
	pd.empty();
	pd.pop();
	pd.push(0);
	pd.size();
	pd.swap(pdd);
	pd.top();

7、stack

//stack
//初始化
	stack<int> sta1;
	stack<int> sta2(sta1);
//其他
	sta1.emplace(1);//类似于push
	sta1.empty();
	sta1.pop();//弹出栈顶元素
	sta1.push(2);//入栈
	sta1.size();
	sta1.swap(sta2);
	sta1.top();//返回栈顶元素

8、list

双向链表

//list
//初始化
	list<int> lis1;
	list<int> lis2(3,5);
	list<int> lis3(lis1);
//其他
	lis1.assign(4,3);
	lis1.assign(lis2.begin(), lis2.end());//重新分配值
	lis1.back();//返回最后一个元素,前提容器非空
	lis1.begin();//返回第一个元素的迭代器
	lis1.cbegin();//返回指向起始的常量迭代器---常量迭代器相对于原来的对应迭代器,就是不能使用* 来修改值
	lis1.cend();//返回指向末尾的常量迭代器
	lis1.clear();//清空
	lis1.crbegin();//返回指向起始的逆向常量迭代器
	lis1.crend();//返回指向末尾的逆向常量迭代器
	lis1.emplace(lis1.begin(),2);//有点等价insert(),不同在于:若链表存储的是一些对象之类的,emplace()可以直接传入参数,不需要像insert插入对象,需要先创建对象,在传给insert,
	lis1.emplace_back(1);//同上,等价于push_back()
	lis1.emplace_front(3);//同上,等价于push_front()
	lis1.empty();//判断是否为空
	lis1.end();//返回指向末尾的迭代器
	lis1.erase(lis1.begin());//删除指定迭代器位置的节点
	lis1.front();//返回第一个节点的元素值
	lis1.insert(lis1.begin(),1);//在指定位置插入指定节点
	lis1.max_size();// //返回list能容纳的最大元素数量
	lis1.merge(lis2);将lis2 合并在lis1后面(lis2为空)
	lis1.pop_back();//删除最后一个元素
	lis1.pop_front();//删除第一个元素
	lis1.rbegin();//返回指向起始的逆向迭代器--即指向最后一个元素,++方向是向链表前移动,即++一次,指向倒数第二个元素
	lis1.remove(1);//删除元素值为1的节点
	lis1.remove_if([](int i) { return (i > 5 || i < 3); });//删除大于5或者小于3的节点
	lis1.rend();//返回指向末尾的逆向常量迭代器--即指向第一个元素前一个位置,--,即按链表向后移动一个,指向第一个元素
	lis1.resize(20);//重新指定容器大小,若大于原来大小,则大于部分默认值填充,若小于原来大小,删除多的部分节点
	lis1.reverse();//翻转容器
	lis1.size();//返回容器大小
	lis1.sort();//进行排序,可以传入参数(Lambda表达式,仿函数),实现从大大到小,或者从小到大
	lis1.splice(lis1.begin(), lis2);//执行完后,在lis1 插入lis2,lis2 为空;即将原始数据加入,insert是副本加入
	lis1.splice(lis1.begin(), lis2, ++lis2.begin());//将lis2的指定节点剪切到lis1的指定位置,lis2的指定节点会被删除;
	lis1.splice(lis1.begin(), lis2, ++lis2.begin(),lis2.end());//将lis2的指定区间节点剪切到lis1的指定位置,lis2的指定区间节点会被删除;
	lis1.swap(lis2);//容器交换
	lis1.unique();删除list中相邻重复的元素,若不相邻,不会删除,可以先排序,在使用该函数;因为涉及判断是否相等,故对于保存自定义类型的,需要传入比较方法,

9、forward_list

单向链表

	forward_list<int> l1;
	forward_list<int> l2(3,4);
	forward_list<int> l3(l1);
	l1.assign({1,2,3,4,5});
	auto a1 = l1.before_begin();//返回一个随机访问迭代器,它指向 forward_list 的第一个元素之前的位置
	auto a2 =l1.begin();//返回一个随机访问迭代器,它指向 forward_list 的第一个元素
	auto a3 = l1.cbefore_begin();//返回一个常量随机访问迭代器,它指向 forward_list 的第一个元素之前的位置。不能用于修改它所指向的对象的内容
	auto a4 = l1.cbegin();
	auto a5 = l1.cend();
	l1.clear();
	l1.emplace_after(l1.cbefore_begin(), 1);//l1是空的时候,使用l1.begin()会报错
	l1.emplace_front(0);//在 forward_list 的开头构造并插入新元素,并将列表的大小增加 1
	l1.empty();
	l1.end();
	l1.erase_after(l1.begin(),l1.end());// ,(]区间。从 forward_list 中删除元素范围并修改 forward_list 的大小。
	l1.front();
	//l1.get_allocator();	//返回与 forward_list 关联的分配器
	l1.insert_after(l1.begin(),1);//通过在后面插入新元素来扩展迭代器位置在 forward_list。该成员函数增加了 forward_list 的大小。
	l1.max_size();//返回 forward_list 可以容纳的最大元素数。此值取决于系统或库实现。
	//void merge (forward_list&& x, Compare comp);
	l1.merge({1,2});
	l3 =  l2;
	l1.pop_front();
	l1.push_front(6);
	l1.remove(1);//从 forward_list 中删除与值匹配的元素,并通过删除的元素数减小 forward_list 的大小。
	l1.remove_if([](int a) {return a % 3==0; });//从满足条件的 forward_list 中删除元素。它删除所有元素谓词返回真。
	l1.resize(10,5);//改变 forward_list 的大小。如果n小于当前大小,则额外的元素被销毁。如果n大于当前容器大小,则在列表末尾插入新元素。如果值指定然后新元素被初始化值。
	l1.reverse();//颠倒 forward_list 中存在的元素的顺序。
	l1.sort();
	l1.splice_after(l1.begin(),l3,l3.begin(),l3.end());//(]
	
	l1.swap(l2);
	l1.unique();//从 forward_list 中删除所有连续的重复元素。它用二元谓词用于比较。

10、map/multimap

//map/multimap ----二叉树实现,自动根据键排序
//初始化
	map<int, int> m1;
	map<int, int> m2(m1);
	map<int, int> m3(m1.begin(), m1.end());
//其他	

	m1[1] = 20;//添加键值对<1,20>
	int num = m1[2];//如果键2不存在,会自动添加,并会返回默认值
	//使用[]注意事项:[]中的是键,假设是m2是是<string,string>类型的键值对,则m2["d"] = "ewew";使用[]来查看值,也是一样的道理,若查询的键不存在,会赋值给该键以默认的值,重点就是,使用[]查询,可能就往容器添加了新的键值对
	m1.at(1) = 100;
	m1.at(0);
	//对at而言,若at里的参数是不存在,就会报异常,无论是赋值还是查询。故at只能修改和查询已经存在的键对应的值
	m1.begin();//返回指向map头部的迭代器
	m1.cbegin();//返回指向map中第一个元素的const迭代器。
	m1.cend();//返回指向末尾的常量迭代器。
	m1.clear();
	m1.count(1);//返回指定元素出现的次数(0 or 1)
	m1.crbegin();//返回指向末尾的常量反向迭代器。
	m1.crend();//返回指向起点的常量反向迭代器。
	
	auto n1 = m1.emplace(3300);//n1.first是插入键值对的,n1.second 是bool值,表示插入有没有成功,若没有成功,则说明已经存在相同键的键值对,first就返回这个已经存在键值对的迭代器;见下面:
	auto n1 = m1.emplace(make_pair(6, 600));//等价于auto n1 = m1.emplace(make_pair(int(6), int(600)));
	auto n2 = m1.emplace_hint(m1.end(),7,700);//基本同上
	auto n4 =m1.try_emplace(1,111);//try_emplace若键不存在则插入,若键存在则不做任何事,感觉和emplace()没区别
	//会用emplace()就可以了吧!!
	//仅当键不存在时才进行插入
	//这两种函数直接在 map 容器中的指定位置构造该键值对。
	m1.insert(m1.begin(),pair<int, int>(4, 200));
	m1.insert(pair<int, int>(4, 200));//先创建该键值对,然后再将该键值对复制或者移动到 map 容器中的指定位置;但是map是有序的,所以指定位置其实没有用
	//比较之下,emplace的效率更高,都会返回一个对组,第一个是插入值的迭代器,第二个是表示是否成功
	m1.empty();
	m1.end();//返回指向map末尾的迭代器
	auto n3 = m1.equal_range(5);//equal_range根据键值,返回一对迭代器的pair对象。如果该键值在容器中存在,则pair对象中的第一个迭代器指向该键关联的第一个实例,第二个迭代器指向该键关联的最后一个实例的下一位置。如果找不到匹配的元素,则pair对象中的两个迭代器都将指向此键应该插入的位置。n3.first,n3.second都是iterator
	m1.erase();
	auto tem = m1.find(1);//查找键是给定值得键值对,若查询到,则返回对应键值对的iteratior,若没找到,返回end();
	//m1.get_allocator();//返回用于构造map的分配器对象。	
	m1.insert_or_assign(3);//插入元素,或若键已存在则赋值给当前元素
	m1.key_comp();//返回比较键的仿函数
	m1.lower_bound(2);//返回键>=给定元素的第一个位置的迭代器
	m1.max_size();//返回map的最大容量。
	m2 = m1;
	m1.rbegin();//返回一个指向map尾部的逆向迭代器
	m1.rend();//返回一个指向map头部的逆向迭代器
	m1.size();
	m1.swap(m2);

	m1.upper_bound(3);//返回键>给定元素的第一个位置的迭代器
	m1.value_comp();//返回值比较的仿函数。
	//m1._Unchecked_begin();
	//m1._Unchecked_end();
	//m1._Unchecked_end_iter();

//multimap相比于map区别在于,multimap可以插入重复键的键值对,map有的函数,multimap基本都有,因为multimap有重复键,故不能使用[];

#include<iostream>
#include<string>
#include<unordered_map>
using namespace std;
int main() {
	unordered_map<int, string> hash;
	auto n1 = hash.emplace(1, "sas");
	auto n2 = hash.emplace(1, "sas1");
	cout << "n1.first->first:   " << n1.first->first << endl;//1
	cout << "n1.first->second: " << n1.first->second << endl;//"sas"
	cout << "n2.first->first:   " << n2.first->first << endl;//1
	cout << "n2.first->second: " << n2.first->second << endl;//"sas"
	cout << "n1.second:  " << n1.second << endl;//1
	cout << "n2.second:  " << n2.second << endl;//0
	return 0;
}

11、unordered_map

//unordered_map
//初始化
	unordered_map<int, int> m1;
	unordered_map<int, int> m2(m1);
	unordered_map<int, int> m3{ {1,100},{2,200} };//或者使用键值对p1,p2初始化
	unordered_map<int, int> m4 = m1;
	m1[1] = 100;
	m1[2] = 200;
	int n1 = m1[3];
	//对[]来说,[]里是键,查询时,若查询的键不存在,则会自己添加默认值的键值对,即执行完,容器内就多了这样一个键值对
	auto n2 = at(2);
	m1.at(2) = 20;//对at而言,不能查询和修改不存在的键,若不存在,会警告
//其他
	m1.begin();//迭代器,不在注释
	auto n2 = m1.bucket(1);
	auto n3 = m1.bucket_count();
	auto n4 = m1.bucket_size(4);
	//对bucket而言,返回给定值的对应哈希值;bucket_count()是返回有多少个bucket,bucket_size(),是返回给定值对应bucket的大小;
	m1.cbegin();
	m1.cend();
	m1.clear();
	auto n5 = m1.count(1);//返回指定元素出现的次数
	m1.emplace(4,400);
	m1.emplace_hint();
	m1.try_emplace();
	//emplace的使用方法和上面的map基本相同,直接对应map里面使用即可。
	m1.empty();
	m1.end();
	m1.equal_range();//同map
	m1.erase();//同map
	auto n6 = m1.find(1);//查找键是给定值得键值对,若查询到,则返回对应键值对的iteratior,若没找到,返回end();
	//m1.get_allocator();//返回用于构造map的分配器对象。	
	m1.hash_function();//返回哈希函数
	m1.insert();//(iterator,待插入的pair),因为unordered_map无序,故指定迭代器位置可以。
	m1.insert_or_assign();//插入元素,或若键已存在则赋值给当前元素
	m1.key_eq();//返回key的相等性谓词
	m1.load_factor();//返回load factor,即容器当前元素数量与桶数量之比
	//m1.lower_bound();//没有提供,不能使用
	m1.max_bucket_count();//返回桶的最大数量
	auto m7 = m1.max_load_factor();//管理每个桶的平均元素数量的最大值
	m1.max_size();//容量
	m1.rehash();//设置桶的数量,并重新对元素进行哈希映射
	m1.reserve();//请求保留桶的数量至给定值
	m1.size();//容器大小
	m1.swap(m2);//交换
	//m1.upper_bound();//没有提供,不能使用
	//m1._Unchecked_begin();
	//m1._Unchecked_end();

总结:map/multimap/unordered_map选择:

容器底层实现数据是否有序数据是否重复是否可以修改查询效率删除效率
map红黑树key有序键不可修改,值可以O(logn)O(logn)
multimap红黑树key有序键不可修改,值可以O(logn)O(logn)
unordered_map哈希表key无序键不可修改,值可以O(1)O(1)

12、set/multimset

//set/multimset
//初始化
	set<int> s1;
	set<int> s2(s1);
	set<int> s3(s1.begin(),s1.end());
//其他
	s1.begin();
	s1.cbegin();
	s1.cend();
	s1.clear();
	s1.count(1);//统计指定元素个数,set不能出现重复的元素,故只能0 or 1
	s1.crbegin();
	s1.crend();
	s1.emplace(1);//类似于insert,作用和前面容器一样
	s1.emplace_hint();
	s1.empty();
	s1.end();
	auto n3 = s1.equal_range();//equal_range根据给定值,返回一对迭代器的pair对象n3。如果该给定值在容器中存在,则pair对象n3中的n3.first指向该元素值的迭代器,n3.second指向该元素的下一位置迭代器。如果找不到匹配的元素,则pair对象中的两个迭代器都将指向此键应该插入的位置。first,second都是iterator
	s1.erase(1);//括号里面就是待删除的值
	s1.find(2);//查找指定元素,若没找到,返回end(),找到就返回对应迭代器
	//s1.get_allocator();
	s1.insert();//类似map
	s1.key_comp();//返回key比较谓词的吧!
	s1.lower_bound();//二分查找一个有序数列,返回第一个大于等于x的数,如果没找到,返回末尾的迭代器位置
	s1.max_size();
	s1.rbegin();
	s1.rend();
	s1.size();
	s1.swap();
	s1.upper_bound();//二分查找一个有序数列,返回第一个大于x的数,如果没找到,返回末尾的迭代器位置
	s1.value_comp();//返回value比较谓词的吧!

13、unordered_set

//unordered_set
//初始化
	unordered_set<int> us1;
	unordered_set<int> us2(us1);
//其他
	us1.begin();
	
	us1.bucket(1);
	us1.bucket_count();
	us1.bucket_size(3);
	//对bucket而言,返回给定值的对应哈希值;bucket_count()是返回有多少个bucket,bucket_size(),是返回给定值对应bucket的大小;
	
	us1.cbegin();
	us1.cend();
	us1.clear();
	us1.count(1);
	us1.emplace();
	us1.emplace_hint();
	us1.empty();
	us1.end();
	us1.equal_range();//
	us1.erase(1);//括号里是待删除的值
	us1.find(2);//括号里是待查找的值
	//us1.get_allocator();
	us1.hash_function();//返回哈希函数
	us1.insert();//
	us1.key_comp();//
	us1.key_eq();//返回key的相等性谓词
	us1.load_factor();///返回load factor,即容器当前元素数量与桶数量之比
	us1.lower_bound();//
	us1.max_bucket_count();//返回桶的最大数量
	us1.max_load_factor();//返回load factor,即容器当前元素数量与桶数量之比
	us1.max_size();
	us1.rehash();//设置桶的数量,并重新对元素进行哈希映射
	us1.reserve();//请求保留桶的数量至给定值
	us1.size();
	us1.swap(us2);
	us1.upper_bound();//
	us1.value_comp();

总结:set/multiset/unordered_set选择:

容器底层实现数据是否有序数据是否重复是否可以修改查询效率删除效率
set红黑树有序不可修改O(logn)O(logn)
multiset红黑树有序不可修改O(logn)O(logn)
unordered_set哈希表无序不可修改O(1)O(1)

14、函数对象(仿函数)

重载函数调用操作符的类,其对象称为函数对象----原因在于,函数对象使用重载()时,行为类似函数,本质是一个类,不是一个函数。

–函数对象使用时,可以像普通函数那般调用,可以有参数,返回值。

class ADD {
public:
	int operator()(int a, int b) {
		return a + b;
	}
};
main(){
	ADD add;
	int sum = add(10, 10);
}

函数对象超过普通函数的概念,函数对象可以有自己的状态----利用类成员记录状态;

class myadd{
public:
	myadd(){ count = 0};
	int operator()(int a,int b){
			count++;
			return a+b;
	}
private:
	int count;
};

–函数对象可以作为参数传递

int doadd(myadd& ad,int v1,int v2){
	return ad(v1,v2);

}

15、Lambda

谓词—即返回值类型为bool的函数对象—若operator()接受一个参数,称为一元谓词,,两个,称为二元谓词;一般用于比较大小,相等的算法时,当做参数传入。如判断struct的大小,这种自定义的类型判断时,需要自己定义比较函数即谓词即仿函数。

Lambda函数:用途类似函数对象,

	vector<int> a{ 1,2,3,4,5,6,7,8 };
	auto sum = count_if(a.begin(), a.end(), [](int x) -> bool {return x % 3 == 0; });

Lambda函数格式:
[capture](parameters) multable ->return-type{statement}

仅当Lambda表达式只有一条返回语句,不用写返回类型,可以自动类型推导,否则使用返回类型后置 ->return-type

Lambad 函数的 [ ]功能:在[]中 ,使用[z],Lambad可以按值访问变量z;[&z], 则可以按引用访问[&],可以按引用访问所有的动态变量,[=],可以按值访问所有的动态变量;所有指的是代码前面出现的变量,当然也可以结合起来用,[z,&] —即按值访问z,按引用访问其他变量。

multable 位置,若不写,则默认Lambda函数是const,mutable可以取消常量性。在使用multable时,必须有参数;

	vector<int> a{ 1,2,3,4,5,6,7,8 };
	int count3 = 0;
	std::for_each(a.begin(), a.end(), [&count3](int x) {  count3 += (x % 3 == 0); });
	//现在 count3 = 2

16、STL中的常见算法

#include<algorithm>
vector<int> v1{ 2,1,3,5,9,6,4,2,1 };
auto a = find_if(v1.begin(), v1.end(), [](int a) {return a >3;}); //vector<int>::iterator a 
auto b = find(v1.begin(), v1.end(), 9);
auto c = adjacent_find(v1.begin(), v1.end());//查找到相等的相邻元素
sort(v1.begin(), v1.end());
auto d = binary_search(v1.begin(), v1.end(), 3);//二分查找某个元素是否存在,返回bool值,只能在有序数组进行使用。
int e = count(v1.begin(), v1.end(), 2);//返回待查找元素出现的次数
auto f = count_if(v1.begin(), v1.end(), [](int a) {return a % 3 == 0; });//按条件统计满足条件的元素个数
sort(v1.begin(), v1.end(), [](int a, int b) {return a > b; });//现在是从大到小排列,对于自定义类型的数据,排序方式要自己写;
random_shuffle(v1.begin(), v1.end());//随机调整次序
reverse(v1.begin(),v1.begin()+4);//翻转指定范围的元素
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值