STL是简单效率不错的工具,尤其几种容器都蛮方便的,掌握好能发挥不错的威力。让你更多的时间去思考解题思路,而不是每次都要写奇奇怪怪的代码模拟简单的功能,让整体代码变的臃肿,想象一下不可能每次排序要自己写把。 总得来说看能使代码思路清晰,简洁。所以我们很有必须学习和掌握基本的STL使用方法。
这里先总结下vector常用的用法。
为了使用vector 首先:
#include <bits/stdc++.h> //很方便的头文件
using namespace std; //做题的话建议写,方便嘛
定义的常用方式:
vector<int> v;
//定义一个空的动态数组,存储int类型元素
vector<int> v(5);
//定义一个初始大小为5的动态数组(默认初始值都为0),存储int类型元素
vector<int> v(5,1);
//定义一个初始大小为5的动态数组,赋值都为1,存储int类型元素
基本操作:
v[i]; // 以下标方式访问元素,很方便.
v.push_back(x); //往尾部插入元素x (常用)
v.insert(it, x); //向迭代器it指向的位置插入x,原位置后移 (蛮方便的,速度也快)。
//举例:v.insert(v.begin(),1); 比较神奇5w次这样的操作 大概0.5s,自己写的O(n)函数大概2.5s
v.size();//返回表长,注意是unsigned类型,如果v.size()为1,减去2就是一个很大的正整数数,看情况转(int)v.size()
v.begin(); // 返回指向首元素的迭代器
v.end(); // 返回指向尾元素下一个位置的迭代器.
v.front(); //取首元素的值
v.back(); // 取尾元素的值
v.empty(); //表为空返回真,否则返回假
v.clear(); //清空表中所有元素
v.pop_back(); // 删除表尾元素
v.erase(it); //删除迭代器it指向的元素
v.erase(st, ed); //删除迭代器st和ed指定的元素[st,ed) (左闭右开)
v.reserve(x); //预分配空间大小为x.
用到vector自然少不了常用的排序sort,那么排序方法有如下几种:
(sort的第三个参数是一个函数指针或一个函数对象,不写就使用默认(自己定义的结构体要排序必须要写比较规则) )
一:默认或使用标准库函数
一个参数
vector<int >v;
sort(v.begin(), v.end()); //默认,从小到大
sort(v.begin(), v.end(), greater<int>()); //从大到小,降序排列
sort(v.begin(), v.end(), less<int>()); // 从小到大,升序排列
两个参数(不想写结构体的话可以用pair<int,int>)
vector<pair<int,int> >v; //pair实质上是一个结构体,其主要的两个成员变量是first和second
v.push_back(make_pair(3,4)); //用make_pair来构造我们需要的pair.
v.push_back(make_pair(4,5));
sort(v.begin(), v.end()); //默认,按第一个数升序排列,若相同则按第二个数升序。
sort(v.begin(), v.end(), greater<pair<int,int> >()); //按第一个数降序排列,若相同按第二个数降序。
sort(v.begin(), v.end(), less<pair<int,int> >()); // 同默认
cout << v[0].first << " " << v[0].second; // 用v[i].first 和 v[i].second 取值
多个参数(当然你想要花里胡哨也可以写 vector<pair<pair<int,int>,int> >v; … 但还是建议写结构体把。
二: 自定义比较函数(常用)
一般形式:
vector<int> v;
bool cmp(int a, int b) { // 比较函数
return a > b; // 降序
// return a < b; 升序
}
sort(v.begin(),v.end(), cmp);
结构体的话类似:
#include <bits/stdc++.h>
using namespace std;
struct test {
int x,y;
test(int _x = 0, int _y = 0) : x(_x), y(_y) {}
};
vector<test> v;
bool cmp(test a, test b) {
return a.x > b.x;
}
int main(void ) {
v.push_back(test(1,2)); //写个构造函数pb时方便很多.
v.push_back(test(3,4));
sort(v.begin(), v.end(), cmp);
cout << v[0].x << endl; // 3
return 0;
}
三 :重载结构体或类的比较运算符
//情况一:在结构体内部重载
#include <bits/stdc++.h>
using namespace std;
struct test {
int x, y;
test(int _x = 0, int _y = 0) : x(_x), y(_y) {}
friend bool operator < (test a, test b) {
return a.x > b.x; //按x降序排序
}
/*或(也可以加上const &更规范,比如在第三个参数写less<test>()时,必须按标准格式写)
bool operator < (const test &a)const {
return x > a.x; //按x降序排序
}
*/
};
vector<test> v;
int main(void ) {
v.push_back(test(1,2)); //写个构造函数pb时方便很多.
v.push_back(test(3,4)); //用的多了,手速狗可以 #define pb pusb_back
sort(v.begin(), v.end()); //不用写第三个参数
cout << v[0].x << endl; // 3
return 0;
}
//情况二:在外部重载
#include <bits/stdc++.h>
using namespace std;
struct test {
int x, y;
test(int _x = 0, int _y = 0) : x(_x), y(_y) {}
};
bool operator < (test a,test b) { //写在外面就不要friend了,参数要写全,更规范就写const &
return a.x > b.x; //按x降序排序
}
vector<test> v;
int main(void ) {
v.push_back(test(1,2)); //写个构造函数pb时方便很多.
v.push_back(test(3,4)); //用的多了,手速狗可以 #define pb pusb_back
sort(v.begin(), v.end()); //不用写第三个参数
cout << v[0].x << endl; // 3
return 0;
}
补充下重载pair,写在全局里无效,主要原因是不在一个namespace中,是先在同名字空间下里找,没找到才会外面找
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
namespace std {
bool operator < (const pair<int,int> &a, const pair<int,int> &b) {
return a.first > b.first;
}
bool operator > (const pair<int,int> &a, const pair<int,int> &b) {
return a.first < b.first;
}
}
vector<pair<int,int> > v;
int main() {
v.pb(mp(1, 2));
v.pb(mp(3, 4));
sort(v.begin(),v.end());
cout << v[0].first << endl; // 3
sort(v.begin(),v.end(), greater<pair<int,int> >());
cout << v[0].first << endl; // 1
}
四 :使用仿函数
#include <bits/stdc++.h>
using namespace std;
struct test {
int x, y;
test(int _x = 0, int _y = 0) : x(_x), y(_y) {}
};
vector<test> v;
struct cmp {
//const 这里编译没有约束,但是对于明确的不可变参加上更严谨,上面的我有的没写,可以比较。
bool operator() (const test &a, const test &b) {
return a.x > b.x; // 按x降序
}
};
int main(void ) {
v.push_back(test(1,2)); //写个构造函数pb时方便很多.甚至可以
v.push_back(test(3,4)); //用的多了,手速狗可以 #define pb pusb_back
sort(v.begin(), v.end(), cmp()); //传入函数对象.
cout << v[0].x << endl; // 3
return 0;
}
五 其他常用
swap(v[1], v[2]); //交换元素.
reverse(v.begin(), v.end()); //反转1234 -> 4321
*max_element(v.begin(), v.end()); //找表里最大的数
*min_element(v.begin(), v.end()); //找表里最小的数
lower_bound(v.begin(), v.end(), x) - v.begin(); //二分法找第一个 大于等于x的下标
upper_bound(v.begin(), v.end(), x) - v.begin(); //二分法找第一个 大于x的下标
v.erase(unique(v.begin(), v.end()), v.end());//去重,1220330770.结果是1203070。一般是排序、去重、离散化时用到.
vector <pair<int,int> >E[maxn]; // 一种建图思路.E[i][j] i为源点,E[i][j].first为第j条边终点, .second为距离