常用STL整理
来源:互联网 发布:linux ddos 防火墙 编辑:程序博客网 时间:2024/05/04 11:53
注:部分陈述来自menci dalao,实在懒得写陈述。
注:蒟蒻整理,有些名词使用不规范,请谅解。
一. 队列(queue) 先进先出的执的排列
STL 在头文件 中提供了先入先出队列 queue。
使用 push() 向队列中加入元素。
使用 front() 获取队首元素(并不删除)。
使用 pop() 删除队首元素。
使用 empty() 判断队列是否为空。
很常用很熟练,就不写代码举例了。
二. 优先队列(priority_queue)
STL 在头文件 中提供优先队列 priority_queue,在任意时间都能取出队列中的最大值。
使用 push() 向优先队列中加入元素,其时间复杂度为O(logn)。
使用 top() 获取优先队列中最大的元素(并不删除),其时间复杂度为O(1)。
使用 pop() 删除优先队列中最大元素,其时间复杂度为O(logn)。
使用 empty() 判断优先队列是否为空。
priority_queue<T> q;//T为想要定义的类型
也可以定义为优先最小值:
priority_queue< T,vector<T>,greater<T> >q;//注意greater<int>后面要加空格。 否则计算机会当右移运算符.
三. 双队列(deque) 连续存储的指向不同元素的指针所组成的数组
感觉用不到,
具体看链接吧
四. 栈(stack) 后进先出的值的排列
STL 在头文件 提供了后入先出栈 stack。
使用 push() 向栈中加入元素。
使用 top() 获取栈顶元素(并不删除)。
使用 pop() 删除栈顶元素。
使用 empty() 判断栈是否为空。
std::stack<int> s;bool flag = s.empty();// flag = true,栈初始为空s.push(23333);s.push(66666);while (!s.empty()) { printf("%d\n", s.top()); s.pop();}// 依次输出 66666,23333
一个栈的使用模板:
#include<iostream>#include<cstdio>#include<stack>using namespace std;stack<int> st;int a[11];int main(){ for(int i=1;i<=10;i++) { cin>>a[i]; st.push(a[i]);//入栈 } st.pop();//弹栈, 后入先弹 while(!st.empty())//判断是否为空 { int k; k=st.top();//访问栈顶 st.pop();//记得弹栈,否则死循环 cout<<k; if(st.size()<5) //求个数 break; } }
比较常用,不再举例。
五. 向量(vector) 连续存储的元素
STL 在头文件 提供了一个可变长的数组 vector,它支持动态的插入、删除操作。
以下代码声明了一个 vector,它的每个元素类型为 int,初始元素数量为 0。
vector<int> v;
以下代码声明了一个 vector,它的每个元素类型为 int,初始元素数量为 n。
std::vector<int> v(n);
vector 提供 begin() 和 end(),分别获取指向第一个元素和最后一个元素之后的迭代器。
需要注意的是,迭代器的头是第0位
以下代码对 v 中的所有元素以升序排序:
std::sort(v.begin(), v.end());
使用 size() 得到 vector 的元素数量,使用 resize() 重新指定 vector 的元素数量。
分别使用 push_back() 和 pop_back() 在 vector 的尾部加入或删除元素,这两个过程的时间复杂度为O(1)O(1)。
使用 insert() 在某个特定的位置插入一个元素,时间复杂度为O(n)。
使用 erase() 删除某个位置的元素,时间复杂度为O(n)。
vector<int> v;// v.size() = 0v.push_back(23333);// v.size() = 1, v = { 23333 }v.insert(v.begin() + 0, 890);// v.size() = 2, v = { 890, 23333 }v.insert(v.begin() + 1, 12345);// v.size() = 3, v = { 890, 12345, 23333 }v.erase(v.begin() + 0);// v.size() = 2, v = { 12345, 23333 }for (nt i = 0; i < v.size(); i++) { printf("%d\n", v[i]);}// 依次输出 12345、23333v.pop_back();// v.size() = 1, v = { 12345 }
注意,在加入元素时,如果 vector 拥有的内存空间不足以存放欲加入的元素,则 vector 会申请一块新的内存,并将旧数据拷贝过去,这个过程通常花费 O(n)O(n) 的时间。
本蒻用vector不太熟练,所以一遍不会用,怕炸;
但最近有个t,stl跑一跑就a了
题目在这,T1
#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cstdio>#include<vector>using namespace std;vector<string> a;string aa;int ans,n;int main(){ scanf("%d",&n); for(int i=0;i<n;i++)cin>>aa,a.push_back(aa); sort(a.begin(),a.end()); vector<string>::iterator new_end; new_end=unique(a.begin(),a.end()); for(vector<string>::iterator i=a.begin();i!=new_end;i++)ans++;printf("%d\n",ans); for(vector<string>::iterator i=a.begin();i!=new_end;i++)cout<<*i<<endl; }
六. 映射(map) 由{键,值}对组成的集合
map的用法有好多,可以用来离散化,记录等,它的操作一般应该都是log n的;
比如:根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
map < vector,int> q; //映射不定长数组,神奇QAQ ——————T2
关于map的离散化:
再举个例子
#include<iostream>#include<map>#include<cstring>#include<string>using namespace std;map<int,string> q;map<string,int> p;int main(){ q[1]="abcd"; p["abcd"]=1; cout<<q[1]; cout<<endl; cout<<p["abcd"];}
输出:
map的用法比较熟了,不举其他例子了。
七. 多重映射(multimap) 允许键对有相等的次序的映射
百度
八. 集合(set) 由节点组成的红黑树,每个节点都包含着一个元素
这里就用代码解释
[set的遍历与两种排序]
#include<iostream>#include<set>using namespace std;int main(){ //set<int,greater<int> > s; ====>从大到小排序 set<int> s;.//默认从小到大 s.insert(5); //第一次插入5,可以插入 s.insert(1); s.insert(6); s.insert(3); s.insert(5); //第二次插入5,重复元素,不会插入 set<int>::iterator it; //定义前向迭代器 //中序遍历集合中的所有元素 for(it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; return 0;}
[set结构体重定义]
struct Info{ string name; double score; bool operator < (const Info &a) const // 重载“<”操作符,自定义排序规则 { //按score由大到小排序。如果要由小到大排序,使用“>”即可。 return a.score < score; }};int main(){ set<Info> s; Info info;//开成info[4]也可以 //插入三个元素 info.name = "Jack";//info[1].name="Jack" info.score = 80;//info[1].score="80" s.insert(info);//s.insert(info[1]) info.name = "Tom"; info.score = 99; s.insert(info); info.name = "Steaven"; info.score = 60; s.insert(info); set<Info>::iterator it; for(it = s.begin(); it != s.end(); it++) cout << (*it).name << " : " << (*it).score << endl; return 0;}/*运行结果:Tom : 99Jack : 80Steaven : 60*/
[set删除与查找]
int main(){ set<int> s; s.insert(5); //第一次插入5,可以插入 s.insert(1); s.insert(2); s.insert(6); s.insert(3); s.insert(5); //第二次插入5,重复元素,不会插入 s.erase(3); //删除键值为3的元素 set<int>::iterator it;//申请一个迭代器,注意stl迭代器的申请方法 it = s.find(6); //查找键值为6的元素存不存在 if(it != s.end()) cout << *it << endl; else cout << "not find it" << endl; it = s.find(3); if(it != s.end()) cout << *it << endl; else cout << "not find it" << endl; //查找元素存在的位置 int pos2=*s.lower_bound(2);//返回第一个大于等于key_value的定位器(1,2,3,4,5中会返回2;1,3,4,5中会返回3) int pos2_next=*s.upper_bound(2);//返回第一个大于key_value的定位器(1,2,3,4,5中会返回3) cout<<pos2<<endl; cout<<pos2_next; return 0;}/* 也可以用下面这种方式查询 #include <cstdio>#include <set>using namespace std;int main() { set <int> s; int a; for(int i = 0; i < 10; i++) s.insert(i); for(int i = 0; i < 5; i++) { scanf("%d", &a); if(!s.count(a)) //不存在 printf("does not exist\n"); else printf("exist\n"); } return 0;}//s.count 记录的是元素出现的次数, 因为在集合中, 最多出现一次, 所以可用此查询 */
[set重定义比较]
struct mycomp{ //自定义比较函数,重载“()”操作符 bool operator() (const int &a, const int &b) { if(a != b) return a > b; else return a > b; }};int main(){ set<int, mycomp> s; //采用比较函数mycomp s.insert(5); //第一次插入5,可以插入 s.insert(1); s.insert(6); s.insert(3); s.insert(5); //第二次插入5,重复元素,不会插入 set<int,mycomp>::iterator it; for(it = s.begin(); it != s.end(); it++) cout << *it << " "; cout << endl; return 0;}/*运行结果:6 5 3 1 */
九. 多重集合(multiset) 允许存在两个次序相等的元素的集合
与set用法一样,详细的,请上翻。
区别就是multiset 允许存在两个次序相等的元素的集合
申请:
multiset<int> a;
一个最近的实例,看T1改之后的
十. 列表(list) 由节点组成的双向链表,每个结点包含着一个元素
还没用到过,手写数组就好了
十一. sort
复杂度是 nlogn (log以2为底),类似于快排。 ※很常用的函数。
sort的功能很强大:
它可以对各种类型排序,只需要写一下自己的排序方式cmp就可以排各种序(vector,struct,string等),
1.需要提醒的是,对于字符串而言,sort默认的排序方式就是按照字典序。
#include<bits/stdc++.h> using namespace std;int main(){ string s[10]; cin>>s[1]>>s[2]>>s[3]>>s[4]>>s[5]; sort(s+1,s+1+5); for(int i=1;i<=5;i++) cout<<s[i]<<" ";}
结果:
2.sort默认由小到大排序,但也可以用封装好的从大到小排序
less<数据类型>()//从小到大排序greater<数据类型>()//从大到小排序
无需定义,在头文件algorithm中
sort(a,a+10,greater<int>()); sort(a,a+10,greater<char>()); sort(a.begin(),a.end()); //对于stl的容器来说
3.对结构体等排序的cmp写法
struct node{int x,y;}e[maxn];bool cmp(node a,node b){return a.x>b.x}//node为结构体类型,按照x的降序排序sort(e+1,e+1+n,cmp);
十二. memeset
memset实际上是用来对一段内存空间全部设置为某个字符,但是对于0,-1的值是可以直接赋的(至于为什么,蒟蒻也不知道)。
对于它的复杂度,据说如果不是赋值字符的话,也是O(n)的,不过常数很小,相对于for循环来说好用很多。
这里有一段测试代码
#include<iostream>#include<cstring>//memset的头文件using namespace std;int a[20],b[20],c[20],d[20],e[20],f[20],g[20];char ch[20];int main(){ memset(a,0,sizeof(a)); memset(b,-1,sizeof(b)); memset(c,1,sizeof(c)); memset(d,127,sizeof(d)); memset(e,127/3,sizeof(e)); memset(f,0x3f3f3f3f,sizeof(f)); memset(g,0x7f7f7f7f,sizeof(g)); memset(ch,'z',sizeof(ch)); for(int i=1;i<=5;i++) cout<<a[i]<<" "; cout<<endl; for(int i=1;i<=5;i++) cout<<b[i]<<" "; cout<<endl; for(int i=1;i<=5;i++) cout<<c[i]<<" "; cout<<endl; for(int i=1;i<=5;i++) cout<<d[i]<<" "; cout<<endl; for(int i=1;i<=5;i++) cout<<e[i]<<" "; cout<<endl; for(int i=1;i<=5;i++) cout<<f[i]<<" "; cout<<endl; for(int i=1;i<=5;i++) cout<<g[i]<<" "; cout<<endl; for(int i=1;i<=5;i++) cout<<ch[i]<<" "; cout<<endl;}
运行结果:
可以看到,memset赋字符好很用,(string好像不行)。
直接赋1的话,其结果已经到了10^7的级别,在int内最大得赋值控制在0x7f7f7f7f就好。而对于spfa等算法int内的最大值inf最佳的赋值是0x3f3f3f3f(和int范围一个级别,但两两相加不爆int),(127/3也可以,稍小一点),因为在松弛的时候如果memset赋的最大值是0x7f7f7f7f,即2319062143稍加上一个数就会爆int。int的最大值2^31-1=2147483647.
对于结构体的清零操作:
struct tre{ int li,ri;}deep[32];int main(){ deep[5].ri=99; memset(&deep,-1,sizeof(deep));//0也可以 cout<<deep[5].ri;}
十三. swap
swap是一个很强大的交换函数,可以交换各种类型(string,vector等,后者很麻烦,不举例)。
十四. lower_bound,upper_bound,binary_search
比较实用又比较玄学,lower_bound和upper_bound的复杂的是二分的复杂度,即logn(以2为底)。
一些容器(set,vector等)也支持lower_bound等操作。
首先要进行sort排序。
lower_bound 用于在一个升序序列中查找某个元素,并返回第一个不小于该元素的元素的迭代器,如果找不到,则返回指向序列中最后一个元素之后的迭代器。通过 -a(a是变量名)的方式获取排名。
upper_bound 用于在一个升序序列中查找某个元素,并返回第一个大于该元素的元素的迭代器,如果找不到,则返回指向序列中最后一个元素之后的迭代器。通过 -a的方式获取排名。
binary_search 用于确定某个元素有没有在一个升序序列中出现过,返回 true 或 false。
三者的例子:
#include <cstdio>#include <algorithm>#include<iostream>using namespace std;int n;int a[10]={-5,1,3,-2,5,6,8,9,4,-10};int main() { sort(a,a+10);//-10,-5,-2,1,3,4,5,6,8,9 int *it1=lower_bound(a,a+10,1); cout<<*it1<<endl;//第一个大于等于1的 输出 1 int *it2=lower_bound(a,a+10,2); cout<<*it2<<endl;//输出 3 int *it3=upper_bound(a,a+10,1); cout<<*it3<<endl;//第一个大于1的 输出 3 int *it4=upper_bound(a,a+10,2); cout<<*it4<<endl;//输出 3 bool b=binary_search(a,a+10,7); cout<<b<<endl;//数组中没有7 输出0 int pos=lower_bound(a,a+10,3)-a; cout<<pos;//输出3的位置 4 (0 1 2 3 4),即第五个 }
容器中 用 container< T> :: iterator it;(其中 container 是容器类型,可以是 vector、set 等,T 是容器中元素的类型。)的方式申请迭代器,
it是container< T> :: iterator类型的数,可以与s.begin() s.end()作比较等操作。(其中s是容器类型的名称,如multiset < int> s;)。
*it指针返回查询的值。这里的it,只支持 it++ 和it - -的操作,不能it+i;
输出时,cout<<*it; 输出指向的值。
对于容器的操作,看之前做的题,T1优化后的
十五. unique
需要先排序,然后用unique进行去重操作,通过-a(a是变量名)获取数量位置
下面的代码演示了读入 n个数,并升序排序并去重后输出。
#include<iostream> #include<vector> #include<algorithm> //unique头文件 using namespace std; vector<int>a; int main() { for(int i=1;i<10;i++) for(int j=0;j<3;j++) a.push_back(i); sort(a.begin(),a.end()); a.erase(unique(a.begin(),a.end()),a.end()); for(int i=0;i<a.size();i++) cout<<a[i]; return 0; } /*也可以这样:int count=unique(a,a+n)-a; for (int i=0; i<count;i++) printf("%d\n", a[i]); */
十六. min,max
较大值较小值,很简单也很常用
int a=1,b=99;c=min(a,b);//c=1d=max(a,b);//d=99
- 常用STL算法整理
- 常用STL整理
- 常用STL库的整理
- STL常用容器用法整理
- STL Vector 常用操作整理(比较全面易懂的整理)
- STL整理
- STL整理
- STL整理
- STL整理
- STL整理
- STL整理
- STL常用
- STL常用
- 常用STL
- 常用stl
- STL 学习整理
- STL Algorithm 整理
- C++ STL 容器整理
- bzoj4917 [Lydsy六月月赛]Hash Killer IV
- Servlet+mysql实现分页技术
- 移动架构32_自定义网络访问框架开发
- Gym
- HTTP协议详解①
- 常用STL整理
- ResNet小结
- 用python做数据分析4|pandas库介绍之DataFrame基本操作 by 是蓝先生
- LeetCode刷题(29)
- Hibernate4 分页查询
- 3、操作系统的基本结构
- JAVA定时器
- Linux下用户组、文件权限详解
- csdn如何转载别人的文章