文章目录
五、STL
5.1优先队列
普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。
在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。
首先要包含头文件#include<queue>
, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队。
优先队列具有队列的所有特性,包括队列的基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。
和队列基本操作相同:
- top 访问队头元素
- empty 队列是否为空
- size 返回队列内元素个数
- push 插入元素到队尾 (并排序)
- emplace 原地构造一个元素并插入队列
- pop 弹出队头元素
- swap 交换内容
prioriy_queue<Type,Container,Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。
一般需要用自定义的数据类型或者比较方式的时候才传入三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆
升序,小顶堆
priority_queue<int,vector<int>,greater<int> >
降序,大顶堆
priority_queue<int,vector<int>,less<int> >
注意 最后‘>’前面有一个空格
5.1.1 基本优先队列
#include<queue>
#include<iostream>
using namespace std;
int main()
{
//基础类型,默认是大顶堆(降序)
priority_queue<int> a;
priority_queue<string> b;
//小顶堆(降序)
priority_queue<int,vector<int>,greater<int> > c;
//入队
for(int i=0;i<5;i++)
{
a.push(i);c.push(i);
}
b.push("abc");
b.push("cab");
b.push("abcd");
//出队
while(!a.empty())
{
cout<<a.top();
a.pop();
}
while(!c.empty())
{
cout<<c.top();
c.pop();
}
while(!b.empty())
{
cout<<b.top();
b.pop();
}
}
运行结果:
43210
01234
cab abcd abc
5.1.2 用pair做优先队列元素
规则:pair的比较,先比较第一个元素,第一个相等比较第二个。
pair是数据类型,不需要再传入Container和Functional,默认是大顶堆,最大的元素优先级最高,先出队
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main()
{
priority_queue<pair<int, int> > a;
pair<int, int> b(1, 2);
pair<int, int> c(1, 3);
pair<int, int> d(2, 5);
a.push(d);
a.push(c);
a.push(b);
while (!a.empty())
{
cout << a.top().first << ' ' << a.top().second << '\n';
a.pop();
}
}
5.2 vector、map、set
#include<iostream> //C++标准输入输出,cin/cout
#include<cstdlib>
#include<cstdio> //c标准输入输出,scanf/printf
#include<algorithm> //常用算法,比如快速排序sort函数
#include<map><vector><string><set> //STL相应模块
#include<cstring> //c语言字符串相关,memset函数所在头文件
map和set都支持的操作有:
count()
insert()//这个vector也支持
find()
erase()
一、vector用法
2.1 vector长度
v.capacity();//容器目前能存储的元素个数
v.size();//当前容器存储的元素个数
v.reverse();//表示预留存储空间但不创建对象,需要用insert或者push_back创建对象
v.resize();//既分配了空间也创建了对象,空间就是capacity,对象就是元素
区别
reverse()只修改capacity大小,不修改size大小
resize()既修改capacity大小,也修改size大小
analogy:
建造一幢房子,这个房子的空间可以容纳50个人,但只是说有这个空间容纳的下,不代表已经有了50个人,这是capacity,当有50个人进入房子的时候,这才是size
reverse想重建这个房子,使房子能装下80人,如果这个房子原来是空的,那么扩建后就还是空的,如果房子里原来有50人,那么扩建后就还有50人(意味着还能再进入30人就满了)
resize是重建这个房子同时把房子填满,如果房子里原来的人比房子的容量小,那么指定一些人进入房子,如果原来的人比房子容量大,就把一些人赶出去。
2.2vector初始化
1.不带参数结构
vector<int> a;
2.带参数结构
(1).初始化vector的大小,但每个元素为默认值0
vector<int> a(10)
(2).初始化大小同时指定初始值
vector<int> a(10,1) //vector被初始化为10个1
3.通过数组地址初始化
int a[5]={1,2,3,4,5};
vector<int> b(a,a+5)
//注意b是用a+5,因为地址是从0到5(左闭右开)
4.通过同类型的vector初始哈
vector<int> a(5,1)//初始化a为5个1
vector<int> b(a)//用a初始化b
5.通过insert初始化
(1) //将同类型的迭代器对应的始末区间(左闭右开)内的值插入到vector中
vector<int> a(6,1);
vector<int> b;
b.insert(b.begin(),a.begin(),a.begin()+3);
//将a[0]~a[2]插入到b的开始处
(2)//数组地址空间实现插入
int a[6]={1,1,1,1,1,1};
vector<int> b;
b.insert(b.begin(),a,a+6);
(3)//插入m个值为n的元素
b.insert(b.begin(),m,n);
6.通过copy函数赋值
vector<int> a(5,1);
int a1[5]={2,2,2,2,2};
vector<int> b(10);
copy(a.begin(),a.end(),b.begin());
//将a中全部元素拷贝到b开始位置
copy(a1,a1+5,b.begin()+5)
//将a1中元素拷贝到b中5~9的位置
2.3 常见的操作
1.insert
(1)插入一个元素
v.insert(位置,元素)
eg:v.insert(v.begin(),e)//用迭代器表示位置
//注意左闭右开区间,如果l=v.size()
//那么v的区间是:v.begin()~v.begin()+l
(2)插入多个元素
v.insert(位置,n,e)//插入n个相同元素e
eg:v.insert(v.begin()+1,2,3)
//在v[1]前面插入2个3
v.insert(位置,beg,end)//插入[beg,end)区间的元素
eg:v.insert(v.begin(),v1.begin(),v1.end())//在v开始处插入v1
2.vector pile[maxn]
定义了maxn个vector:
pile[i] (i=0~maxn-1),每个pile[i]是一个可增长的数组(vector)
3.使用模板注意
模板使用的时候不可以用下标只能用迭代器
1.sort
错误:sort(v,v+n)
正确:sort(v.begin(),v.end())
2.
lower_bound(v.begin(),v.end(),x)
upper_bound(v.begin(),v.end(),x)
3.
find(a.begin(),a.end(),10);
//在a中找10
4.back和front
v.back()//返回v的最后一个元素
v.front()//返回v的第一个元素
还可以用back和front给第一个、最后一个元素赋值
5.删除和添加
1.添加
v.push_back(e);//向v的结尾处加入e
2.删除
(1)删除最后一个
v.pop_back();
(2)删除指定位置
v.erase(v.begin(),v.begin()+3);
//删除了v[0].v[1].v[2]
(3)清空v
v.clear();
6.其他
empty()
return 0
不为空
return 1
为空
2.4 遍历
数组下标
for(int i=0;i<v.size();i++)
{
cout<<v[i]<<endl;
}
迭代器
for (vecotr<int>::iterator iter=v.begin();iter!=v.end();iter++)
{
std::cout<<*iter<<endl;
}
C++11 aotu
for(auto i:v)
{
cout<<v[i]<<endl;
}
三、map的用法
map<key_type,value_type> name;
在map总,元素是按照key值进行排序的
1.插入
map<char,int> ctoi;
1.ctoi.insert(pair<char,int>("Monday",1));
2.ctoi.insert(make_pair("Monday",1));
3.ctoi.insert({"Monday",1});
4.ctoi["Monday"]=1;
2.count
ctoi.count("某个key值");
//map中存在return 1;否则return 0
3.迭代器遍历
map<char,int>::iterator item=ctoi.begin();
while(item!=ctoi.end())
{
用item->first取key值
item->second取value值
}
4.查找
map<char,int>::iterator iter;
if((iter=ctoi.find("要查找的元素"))!=ctoi.end())
5.删除
erase可以删除指定key值的元素
ctoi.erase("name")
四、set用法
set内部元素在自动排序且去重
count() 用来查找set中某个某个键值出现的次数因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了。
erase(iterator) 删除定位器iterator指向的值
erase(first,second) 删除定位器first和second之间的值
erase(key_value) 删除键值key_value的值
find() 返回给定值的定位器,如果没找到则返回end()。
1.遍历
set<int> testset;
通常使用迭代器
for(set<int>::iterator it=testset.begin();it!=testset.end();++it)
cout<<*it<<endl;
*这种只有在C++11编译器下可以通过
for(auto i:testset)
cout<<i<<endl;
2.insert
set<int> testset;
testset.insert(元素);
testset.insert(a,a+5);
testset.insert(v.begin(),v.end());
3.初始化
1 用数组初始化
int a[5]={1,2,3,4,5};
set<int> s(a,a+5);
2 用另一个set初始化
set<int> a;
set<int> testset(a);