STL
题目链接:
结构体排序
http://acm.hdu.edu.cn/showproblem.php?pid=5702
map
http://acm.hdu.edu.cn/showproblem.php?pid=1004
http://acm.hdu.edu.cn/showproblem.php?pid=1075
https://ac.nowcoder.com/acm/problem/206077(前缀和)
set/multiset/priority_queue
http://www.fjutacm.com/Problem.jsp?pid=3105
http://www.fjutacm.com/Problem.jsp?pid=4216
http://www.fjutacm.com/Problem.jsp?pid=4181
deque
https://codeforces.com/contest/1352/problem/D
lower_bound
http://www.fjutacm.com/Problem.jsp?pid=4063
简介
STL是Standard Template Library的简称,中文名标准模板库。从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。
- STL可分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分。
算法
- 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成。
sort(快排)
- 作用:sort函数用于C++中,对给定区间所有元素进行排序,默认为升序,也可进行降序排序。
- 复杂度:快速排序 n*log2n,比冒泡之类的排序算法效率要高
- 头文件:#include< algorithm>
- 语法
Sort(start,end,cmp)
参数
(1)start表示要排序数组的起始地址;
(2)end表示数组结束地址的下一位;
(3)cmp用于规定排序的方法,可不填,默认升序。
#include<iostream>
#include<algorithm>
using namespace std;
#define maxvex 100001
struct Student
{
int score;//分数
int Sno;//学号
}stu[maxvex];
bool cmp(Student a,Student b)
{
return a.score > b.score || (a.score == b.score&&a.Sno < b.Sno);
//将分数高的同学排在最前面,如果两个同学分数一样,则按他们的学号大小进行排序
}
int main()
{
stu[0].Sno = 1;
stu[0].score = 10;
stu[1].Sno = 2;
stu[1].score = 100;
stu[2].Sno = 3;
stu[2].score = 50;
stu[3].Sno = 4;
stu[3].score = 50;
sort(stu, stu + 4, cmp);
for (int i = 0; i < 4; i++)
{
cout << stu[i].Sno << " " << stu[i].score << endl;
}
system("pause");
return 0;
}
max,min
- 头文件:#include< algorithm>
- 返回两个元素的最大值或最小值
cout << "3,4中的最小值是" << min(3, 4) << endl;
cout << "3,4中的最大值是" << max(3,4) << endl;
lower_bound,upper_bound
- 头文件:#include< algorithm>
- 作用
- lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。
- upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。
- 通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
- 复杂度:二分查找 o(logn)
int list[8] = { 0,1, 2, 3, 4, 4, 4, 6 };
int idx1 = lower_bound(list, list + 8,4)-list;
int idx2 = upper_bound(list, list + 8, 4) - list;
cout << "idx1=" << idx1 << endl;
cout << "idx2="<<idx2 << endl;
cout << "第一个大于等于4的数是"<<list[idx1] << endl;
cout << "第一个大于4的数是" << list[idx2] << endl;
unique
- 头文件:#include< algorithm>
- 作用
unique的作用是去除重复的元素(只保留一个),但是它不是将重复的元素直接删除,而是丢到数组末尾藏起来。
返回值为去重后数组的尾地址- 由于uinique去除的是相邻重复元素,需要先对数组进行排序
- 通过返回的地址减去起始地址begin,得到得到去重后的数组长度。
- 语法
unique(start,end)
参数
(1)start表示要排序数组的起始地址;
(2)end表示数组结束地址的下一位;int list[8] = { 0, 1, 2, 3, 4, 4, 4, 6 }; int size=unique(list, list + 8)-list;//得到去重后的数组长度 for (int i = 0; i < size; i++) { cout << list[i] << " "; }
容器
-
定义方法:container<type>
其中container为容器类型,type为数据类型 -
迭代器
对容器中的元素进行遍历需要用到迭代器,迭代器的定义方法为:container<type>::iterator it
简单来讲就是定义了一个指向容器的指针- 容器中常用的迭代器指针
begin():返回首元素的迭代器指针
end():返回尾元素后一个位置的迭代器指针
rbegin():返回尾元素的迭代器指针
rend():返回首元素前一个位置的迭代器指针
- 容器中常用的迭代器指针
set
- set具备的两个特点:
1. set中的元素都是排序好的
2. set中的元素都是唯一的,没有重复的 - 头文件:#include< set>
- 声明:set<int>s
常用方法
insert()–在集合中插入元素
begin(); 返回指向第一个元素的迭代器
end(); 返回指向迭代器的最末尾处(即最后一个元素的下一个位置)
count(); 返回某个值元素的个数
size()–集合中元素的数目
erase()–删除集合中的元素
find()–返回一个指向被查找到元素的迭代器
empty(); 如果集合为空,返回true
clear(); 清除所有元素
lower_bound()–返回指向大于(或等于)某值的第一个元素的迭代器
upper_bound()–返回大于某个值元素的迭代器
示例
set<int> s;//创建一个int型的set集合
s.insert(1);
s.insert(2);
s.insert(8);
s.insert(3);
s.insert(1);//因为前面插入了1,所以这行代码会被忽略
set<int>::iterator it;//定义前向迭代器用于遍历
for (it = s.begin(); it != s.end(); it++){
cout << *it << " ";
}
cout << endl;
//size
cout << "集合中元素个数为:" << s.size() << endl;
//find
it = s.find(3);
cout << "找到集合中等于3的元素并存在it所指地址,it所指地址存放的数为:" <<*it<< endl;
//count
cout <<"集合中等于8的元素有"<< s.count(8)<<"个" << endl;
//erase
//删除指定值的元素
s.erase(1);
cout << "删除集合中等于1的元素" << endl;
for (it = s.begin(); it != s.end(); it++){
cout << *it << " ";
}
//clear
s.clear();
cout << "集合清空" << endl;
if (s.empty())
{
cout << "set中没有元素" << endl;
}
cout << s.size() << endl;
multiset
multiset容器里封装的是红黑树,它可以看成一个序列,插入一个数,删除一个数都能够在O(logn)的时间内完成,而且他能时刻保证序列中的数是有序的,并且序列中可以存在重复的数。
map
pair
- pair的应用
- pair是将2个数据组合成一组数据,当需要这样的需求时就可以使用pair,如stl中的map就是将key和value放在一起来保存。另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair。
- pair的实现是一个结构体,主要的两个成员变量是first 和second
具体用法:
- 定义(构造):
pair<int, double> p1; //使用默认构造函数
pair<int, double> p2(1, 2.4); //用给定值初始化
pair<int, double> p3(p2); //拷贝构造函数
- 访问两个元素(通过first和second):
pair<int, double> p1; //使用默认构造函数
p1.first = 1;
p1.second = 2.5;
cout << p1.first << ' ' << p1.second << endl;
概述
- map是一类关联式容器。可以建立Key - value的对应。key 和 value可以是任意你需要的类型。
对于迭代器来说,可以修改实值,而不能修改key。 - map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的
- STL map中重载operator()<的运算符,默认是采用小于号来排序的,string类型的关键字排序是按照字符串中的字典序排序,如果第一个字符相同就比较第二个,如果前两个都相同就比较第三个,以此类推… 如果关键词是int型的话,就直接按照大小排序了。
- 头文件:#include<map>
- 声明:map<string,int>mp
常用方法
- 四种插入方法:
- 方法一:pair
map<int, string> mp;
mp.insert(pair<int,string>(1,"aaaaa"));
- 方法二:make_pair
map<int, string> mp;
mp.insert(make_pair<int,string>(2,"bbbbb"));
- 方法三:value_type
map<int, string> mp;
mp.insert(map<int, string>::value_type(3,"ccccc"));
- 方法四:[]
map<int, string> mp;
mp[4] = "ddddd";
-
删除
-
erase(iterator it):删除迭代指针it处元素
-
erase(iterator first,iterator last):删除[first, last)之间元素
-
erase(const Key& key):删除键值等于key的元素
-
-
大小、判断空函数
- size() :返回容器元素个数
- empty() :判断容器是否空,若返回true,表明容器已空。
-
查找
- find(const Key& key):查找键值等于key的元素,返回它的迭代器指针
unorder_map
unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。
multimap
map和multimap不同之处在于:map只允许key与 value一一对应;multimap一个key可对应多个value;
vector
概述
vector是一个容器,它能够存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,可以动态改变大小。
- 头文件:#include<vector>
- 声明:一维:vector<int>a
二维:vector<int>vec[maxvex]
封装结构体:vector<Node>edge
常用方法
clear() 移除容器中所有数据。
empty() 判断容器是否为空。
erase(pos) 删除pos位置的数据
erase(beg,end) 删除[beg,end)区间的数据
front() 传回第一个数据。
insert(pos,elem) 在pos位置插入一个elem拷贝
pop_back() 删除最后一个数据。
push_back(elem) 在尾部加入一个数据。
resize(num) 重新设置该容器的大小
size() 回容器中实际数据的个数。
begin() 返回指向容器第一个元素的迭代器
end() 返回指向容器最后一个元素的迭代器
stack
概述
stack翻译为栈,是STL中实现的一个后进先出的容器。
- 头文件:#include<stack>
- 定义:stack<int>stk
常用方法
empty() 堆栈为空则返回真
pop() 移除栈顶元素
push() 在栈顶增加元素
size() 返回栈中元素数目
top() 返回栈顶元素
queue
概述
对于 queue 来说,只能访问 queue 的第一个和最后一个元素:即只能在容器的末尾添加新元素、或只能从头部移除元素,保持 FIFO(先进先出)原则。
常用方法
- push():在队列尾部插入一个元素
- pop(): 将队首元素弹出
- size(): 返回队列中元素的个数
- empty(): 如果队列为空,返回真值
- front(): 返回队列中第一个进入的元素,即第一个元素
- back(): 返回队列中最后一个进入的元素
priority_queue
- 概述:优先队列时一种比较重要的数据结构,它是有二项队列编写而成的,可以以O(log n) 的效率查找一个队列中的最大值或者最小值,其中是最大值还是最小值是根据创建的优先队列的性质来决定的。
- 声明:
priority_queue< type, container, function >
其中- type 为数据类型,
- container为容器类型(默认为vector) ,
- function 为比较方法(less or greater)
在只使用第一个参数时,优先队列默认是一个最大堆,每次输出的堆顶元素是此时堆中的最大元素。
例如:
//构造一个空的优先队列(此优先队列默认为大顶堆)
priority_queue<int> big_heap;
//另一种构建大顶堆的方法
priority_queue<int,vector<int>,less<int> > big_heap2;
这时可以从队首取出最大的元素
反之,若要取最小的元素,则如下定义:
priority_queue<int,vector<int>,greater<int> > big_heap2;
需要注意的是,如果使用less和greater,需要头文件:
#include <functional>
deque
双端队列,可以在队头和队尾删除或添加元素
- 方法:
push_back():从队尾添加元素
push_front(): 从队头添加元素
pop_back():从队尾删除元素
pop_front():从队头删除元素