常用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
原创粉丝点击