zoukankan      html  css  js  c++  java
  • STL中的容器

    .vector

    前面已经讲了vector创建的方法。现在主要讲他的方法的迭代器等注意事项。

    迭代器其实就是广义指针,它可以是指针,也可以是一个可对其执行类似指针的操作-----如解除引用的对象。可以将指针广义化为迭代器,让STL能够为各种不同的容器类(包括那些简单指针无法处理的类)提供统一的接口。每个容器类都定义了一个合适的迭代器,该迭代器的类型是一个名为iterator的typedef,其作用域是整个类。

    begin()返回一个指向容器第一个元素的迭代器,end()返回一个表示超过容器尾的迭代器

    例如要为vector的double类型规范一个迭代器,可以这样做:

    vector<double>::iterator pd//pd an iterator

    wector<doublr>scores

    可以用迭代器pd执行这样的操作:

    pd=scores.begin();

    *pd=22.3;

    pd++;

    迭代器的行为就像是指针,c++11有自动类型推断功能;

    例如:可以用

    auto pd=scores.begin();来代替vector<double>::iterator pd=scores.begin();

    可以用以下代码来显示容器内容:

    for(pd=scores.begin();pd!=scores.ends();pd++)

    cout<<*pd;

    需要添加元素的话 只需要v.push_back();即可

    需要删除数组的元素的话,使用v.erase(v.begin()+1)

    它可以删除一段区间的所有元素。v.erase(v.begin()+1,v.begin()+5); 删除的是下标1,2,3,4的元素。并没有删除下标为5的元素,这一点需要注意!删除的是到v.begin()+5前一个元素为止的。

    插入元素的话  使用v.insert(v.begin(),1);在第零个元素前面插1//insert()第一个参数是地址

     #include<iostream>
    #include<vector>
    using namespace std;
    int main()
    {
        vector<int>::iterator it;
        vector<int >  v,m;
        int i;
        for(i=0;i<10;i++)//添加10个元素 1,2,3....
        {
            v.push_back(i);
        }
        for(it=v.begin();it!=v.end();it++)//遍历一下整个数组
        cout<<*it<<" ";
        cout<<endl;
        v.erase(v.begin()+1);//删除的是第一个元素(下标从0开始)
                            // 也就是1 ,所以现在是0,2,4...9
     v.insert(v.begin()+1,1);//把删除的再加进去 (在指定位置前面加)
        v.erase(v.begin()+1,v.begin()+4);//删除的第1,2,3 的元素共三个元素
        //也就是剩下的是 0,4,5,6,7,8,9
        v.insert(v.end(),10);
        for(it=v.begin();it!=v.end();it++)//遍历一下整个数组
        cout<<*it<<" ";
        cout<<endl;    
        m.push_back(20);
        m.push_back(30);
          for(it=m.begin();it!=m.end();it++)//遍历一下整个数组
        cout<<*it<<" ";
        v.swap(m);
        for(it=v.begin();it!=v.end();it++)//遍历一下整个数组
        cout<<*it<<" ";
        cout<<v.size()<<endl;
        return 0;
    }

    v.insert(v.begin()+2,2);在第二个元素前插2

    v.insert(v.end(),1000);注意 这个是在最后一个元素后面插的1000,而并不是最后一个的前面。大家可以自己自己试试。

    v.size();元素的个数

    v.clear();清除所有元素

    #include<iostream>
    #include<vector>
    using namespace std;
    int main()
    {
        vector<int>::iterator it;
        vector<int >  v;
        int i;
        for(i=0;i<10;i++)//添加10个元素 1,2,3....
        {
            v.push_back(i);
        }
        for(it=v.begin();it!=v.end();it++)//遍历一下整个数组
        cout<<*it<<" ";
        cout<<endl;
         v.erase(v.begin()+1);//删除的是第一个元素(下标从0开始)
                            // 也就是1 ,所以现在是0,2,4...9
        v.insert(v.begin()+1,1);//把删除的再加进去
        v.erase(v.begin()+1,v.begin()+4);//删除的第1,2,3 的元素共三个元素
        //也就是剩下的是 0,4,5,6,7,8,9
        for(it=v.begin();it!=v.end();it++)//遍历一下整个数组
        cout<<*it<<" ";
        cout<<endl;    
        cout<<v.size()<<endl;//看一下数组的大小
        v.clear();
        cout<<v.size()<<endl;
        return 0;
     }

     1.push_back   在数组的最后添加一个数据
    2.pop_back    去掉数组的最后一个数据
    3.at                得到编号位置的数据
    4.begin           得到数组头的指针
    5.end             得到数组的最后一个单元+1的指针
    6.front        得到数组头的引用
    7.back            得到数组的最后一个单元的引用
    8.max_size     得到vector最大可以是多大
    9.capacity       当前vector分配的大小
    10.size           当前使用数据的大小
    11.resize         改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
    12.reserve      改变当前vecotr所分配空间的大小
    13.erase         删除指针指向的数据项
    14.clear          清空当前的vector
    15.rbegin        将vector反转后的开始指针返回(其实就是原来的end-1)
    16.rend          将vector反转构的结束指针返回(其实就是原来的begin-1)
    17.empty        判断vector是否为空
    18.swap         与另一个vector交换数据

    vector的元素不仅仅可以是int,double,string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。

    reverse(vec.begin(), vec.end());

    #include<iostream>
    #include<vector>
    #include<algorithm>
    using namespace std;
    struct rect
    {
     int id;
     int length;
     bool operator<(const rect &a) const
     {
      if(id!=a.id)
      return id<a.id;
      else
      return length<a.length;
     }
    };
    int main()
    {
        int n;cin>>n; vector<rect>vec(n);
        for(int i=0;i<n;i++)
        cin>>vec[i].id>>vec[i].length;
        reverse(vec.begin(), vec.end());//大到小排序,sort(vec.begin(), vec.end());是从小到大排序
        for(int i=0;i<n;i++)
        cout<<vec[i].id<<" "<<vec[i].length<<endl;
     return 0;
     }

    ap本身是键值(key)和映射值(value)的一个映射。其中key和value可以选择任意数据类型。

    (1)创建一个map

    这里使用最简单的一种方法,就是直接定义一个map,在里面写上key和value的类型,再定义map的名字。

    map <int,int> mp;

    (2)向map中添加元素

    第一种是直接使用map的下标进行添加,就像使用数组一样。比如:

    for(int i = 1;i <= n;i++) mp[i] = i * 100;

    第二种是使用insert函数,将一个pair元素进行插入。比如:

    for(int i = 1;i <= 10;i++) mp.insert(make_pair(i,i*100));

    以及还有许多神奇的添加方式,在这里不一一讲述了……

    (3)在map中查找元素

    如果要直接查找元素在map中出现过多少次,那么可以使用count函数,比如:

        map <int,int> mp;
        rep(i,0,19) mp.insert(make_pair(i,i*100));
        if(mp.count(1)) printf("Yes
    ");

    注意这里的count是直接查找键值(key)。

    而且因为map中会自动对相同键值去重……所以count相当于只会告诉你这个元素是否有出现过。如果想使用count计算元素出现次数可以使用multimap。

    map还有find()函数,可以返回指向所查找元素的迭代器,如果没有此元素就返回指向map尾部的迭代器。

    比如:

    map <int,int> :: iterator itf;
        itf = mp.find(19);
        if(itf != mp.end()) itf->second = 20;

    注意因为itf是一个迭代器(实际上是指针),所以我们使用了->,如果不愿意使用的话,也可以写成:

    (*itf).second

    最暴力的方式就是直接在map中用迭代器遍历,比如这样:

    map <int,int> :: iterator it;
        for(it = mp.begin();it != mp.end();it++) printf("%d->%d
    ",it->first,it->second);

    因为在map中元素的地址是相连的,所以直接it++即可。如果不愿意用->就使用上面的写法。

    还有非常强劲的查找方式,那就是直接使用lowerbound和upperbound。这里要提一下map里面的排序,他是自动按key值从小到大排序,也就是说不可以对map使用sort。

    lowerbound和upperbound与平时在数组上的用法都是一样的,一般来说支持key值查找(value作为第二关键字可不可行我还不知道……)一般来讲,我们映射都是一一映射,所以key值应该都是唯一的,直接在key值上查找就可以了。

    特别的,如果lower/upperbound找不到元素的话,返回指向容器末尾的迭代器。

    (返回的类型如果你开了代码补全可以看到……不过很影响码速)

    (4)map中删除元素

    删除元素一般来说有三种操作。第一种是直接使用erase函数往里面传实际值,比如:

    mp.erase(0);

    第二种就是向里面传一个迭代器,比如:

    mp.erase(mp.begin());//显然begin函数返回的是一个迭代器!!

    第三种就是传两个迭代器,注意这样删除的是一个左闭右开的区间,比如:

    复制代码
        
        map <int,int> mp;
        rep(i,0,19) mp.insert(make_pair(i,i));
            map <int,int> :: iterator itf;
        itf = mp.upper_bound(15);
        mp.erase(mp.begin(),itf);    
    复制代码

    这样删完之后,你会发现元素还剩15~19,(15没有被删去),用upperbound的话就是16~19了。

    这些操作已经基本够用了……还有一个很厉害的swap。这里的swap函数直接交换的是两个map容器,而不是元素。

    (下面代码是偷来的)

    按 Ctrl+C 复制代码
    按 Ctrl+C 复制代码

    就是这样啦!

    3.set

    set即集合,内部是使用红黑树实现的(这么强劲的数据结构蒟蒻学不会QAQ)。不过set的操作还是非常值得学一学的。

    (1)创建一个set。

    set <int> q;

    这是最简单的写法,里面的变量类型是任意的,比如什么pair啦或者是自己定义的结构体。

    注意set在你没有进行重载运算符之前,默认是一个小根堆,而且会自动去重。

    (2)向set里面插入元素

    插入元素好像有好多好多奇妙的方法……不过我还是说最简单的吧,就是直接使用insert函数(set可不再支持用下标插入函数了)比如:

    q.insert(3);//这是int版本的
    q.insert((node){a,b,c})//如果你自定义一个结构体,就可以这么传(和平时往队列里面压一样)

    (3)在set中查找元素

    这里面好多函数在map中都介绍过了,而且在set中的用法和在map中基本一样,比如count,find等等。

    不过,我们可以对结构体进行运算符重载,之后就可以愉悦的使用lowerbound对你想要的东西进行查找。

    支持多关键字,多种排序方式,我们举个例子。

    复制代码
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<set>
    #include<vector>
    #include<utility>
    #include<map>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    struct node
    {
        int sum,val;
        bool operator < (const node &g)const
        {
             if(sum == g.sum) return val > g.val;
             return sum < g.sum; 
        }
    }
    set <node> q;
    int main()
    {
        for(int i = 1;i <= n;i++) q.insert((node){a,b,c});
        set <node>  :: iterator it;
        it = q.lower_bound((node){1,2,3});
        //这样就可以查找了
        return 0;  
    }
    复制代码

    非常强力的查找方式。然后……注意重载运算符只能重载小于号。

    注意lowerbound返回第一个大于等于查找键值的元素,而upperbound返回的是最后一个大于等于查找键值的元素。

    (4)在set中删除元素

    这些函数的用法和map基本是一样的,不加以赘述。

    具体的操作也就是这些了……set同样是需要用迭代器来加以访问。

  • 相关阅读:
    第十三篇:一点一滴学ibatis(二)映射文件
    第十二篇:随手记一下javaBean的setter,getter方法的命名问题
    第十一篇:一点一滴学ibatis(一)
    第十篇:javaScript中的JSON总结
    第九篇:Spring的applicationContext.xml配置总结
    第八篇:ZTree操作总结
    第六篇:fastJson常用方法总结
    第五篇:zTree节点的一些操作,权当备份
    第四篇:java读取Excel简单模板
    测试驱动android
  • 原文地址:https://www.cnblogs.com/flyljz/p/10993518.html
Copyright © 2011-2022 走看看