关于c++中的STL的学习与再认识(三)

上一篇讲了经常用到和非常重要的迭代器。

Vertor中的数据操作

可以用insert()函数往Vertor中插入一个元素:

    int n[] = { 22, 33, 11, 44, 55, 66, 99, 55, 88 };
    vector<int> v1(n, n + 9);
    vector<int> v2(n, n + 2);
    vector<int>::iterator it = v1.begin();
    v1.insert(it + 1, 31);  //22, 31, 33, 11, 44, 55, 66, 99, 55, 88 

**特别注意:**insert()函数返回值类型并不是void,而是返回一个迭代器,此时的it值会改变,指向一块不清楚的内存,将不在是v1.begin();因此以下用法会出错。

    v1.insert(it + 1, 31);  //22, 31, 33, 11, 44, 55, 66, 99, 55, 88 
    v1.insert(it, 32);

第一次插入正确,之后it将不在指向初始迭代器,出错。想继续插入的情况下,必须为insert()函数设置返回值。

    it = v1.insert(it + 1, 31);  //22, 31, 33, 11, 44, 55, 66, 99, 55, 88 
    v1.insert(it, 32);//22, 32, 31, 33, 11, 44, 55, 66, 99, 55, 88 

此外,insert()函数还有以下用法:

    int n[] = { 22, 33, 11, 44, 55, 66, 99, 55, 88 };
    vector<int> v1(n, n + 9);
    vector<int> v2(n, n + 2);
    vector<int>::iterator it = v1.begin();
    it = v1.insert(it + 1, 31);  //22, 31, 33, 11, 44, 55, 66, 99, 55, 88 
    it = v1.insert(it, 32);//22, 32, 31, 33, 11, 44, 55, 66, 99, 55, 88
    it = v1.insert(it, 3, 100);//22,100,100,100 32, 31, 33, 11, 44, 55, 66, 99, 55, 88
    it = v1.insert(it, all(v2));//22, 22, 33 ,100,100,100 32, 31, 33, 11, 44, 55, 66, 99, 55, 88

    it = v1.erase(v1.begin() + 1);  //22, 33 ,100,100,100 32, 31, 33, 11, 44, 55, 66, 99, 55, 88  *it = 33;
    it = v1.erase(v1.begin() + 3, v1.begin() + 5); //22, 33 ,100 32, 31, 33, 11, 44, 55, 66, 99, 55, 88  *it = 32;
    cout << *it << endl;

在指定地方插入多个相同的值,返回多个插入值的第一个的位置;
在指定地方插入某一区间的值;

erase()函数:
删除指定位置的一个数,返回删除后第一个数的下标;
删除指定区间的数据,返回删除后第一个数的下标;
切记有返回值
具体实例看代码。

Set

容器特性:
* 添加一个元素,若元素已存在,舍弃;
* 移除元素
* 获取元素个数(不同元素的个数)
* 检测集合中是否存在某个元素

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <set>
using namespace std;

void print_set(set<int> s)
{
    for (set<int>::iterator it = s.begin(); it != s.end(); it++)
        cout << *it << "  ";
    cout << endl;
}

int main()
{
    set<int> s;
    for (int i = 1; i < 10; i++)
        s.insert(i);
    print_set(s);    //1, 2, 3, 4, 5, 6, 7, 8, 9
    s.insert(10);      //1, 2, 3, 4, 5, 6, 7, 8, 9,10
    s.insert(11);   //1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
    s.erase(10);    //1, 2, 3, 4, 5, 6, 7, 8, 9,11
    s.erase(s.find(2), s.find(4));  //1, 2, 3, 4, 5, 6, 7, 8, 9, 11
    print_set(s);
    cout << s.size() << endl; //8

    cout << endl;
    system("pause");
    return 0;

}
  • 在O(log N)(N是set中对象的个数)的时间复杂度下添加,移除元素,并检测元素时候存在
  • 常数时间复杂度O(1)返回set的元素个数
  • set没有push_back()函数,因为set中元素的添加顺序不是很重要。insert()最常用的是插入一个元素,返回这个元素的迭代器和一个布尔值(是否插入成功)
  • set不是线性容器,不能用下标获取set的值。遍历set元素的唯一方法是使用迭代器(print_set函数)
  • 关于find()函数:有一个全局find(),输入两个迭代器和一个元素,时间复杂度为O(N)。但set和map(包括multiset,hash_map)中搜索元素时,不要使用全局find(),而应该使用set::find(),时间复杂度为O(logN)。
  • set中没有排序函数。set有一个区间构造函数。
vector<int> v;

set<int> s(all(v));
vertor<int> v2(all(s));

上述中,v2与s包含相同元素,并且移除了v中重复的元素,可以对v2进行排序。任何可比较的元素都可以存储在set中。

Map

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <set>
#include <map>
using namespace std;

void print_map(map<string ,int> m)
{
    for (map<string, int>::iterator it = m.begin(); it != m.end(); it++){
        cout << it->second << "  ";
    }
    cout << endl;
}

int main()
{
    map<string, int> m;
    m["first"] = 1;
    m["second"] = 2;
    m["third"] = 3;
    int sum = m["first"] + m["third"];
    cout << sum << endl;  //4
    cout << m.find("second")->second << endl;  //2
    cout << (*m.find("second")).second << endl;  //2
    print_map(m);

    system("pause");
    return 0;

}

可以看到:map和set非常像,只是它包含的不只是值,而是键值对pair<key,value>.Map保证最多只有一个键值拥有指定键。
* 遍历map只能用迭代器,迭代器是键值对,用it->second来取值。
* 非常相爱那个python中字典。

注意事项:
从内部看,map 和 set 几乎都是以红黑树的结构存储。要记住的是,遍历容器时 map 和 set 的元素总是按升序排列。而这也是为何在遍历 map 或 set时,极力不推荐改变键值的原因:如果所做的修改破坏了元素间的顺序,这至少会导致容器的算法失效。

常用算法

大部分算法都生声明在标准头文件#include<algorithm>。首先,STL提供了三种很简单的算法:min(a,b),max(a ,b ),swap(a,b)。
比较常用的有sort()函数:sort(begin, end) 按升序对一个区间的元素进行排序。注意,sort() 需要随机存取迭代器,因此它不能作用在所有类型的容器上。

find():find()。调用 find(begin, end, element) 返回‘element’首次出现时对应的迭代器,如果找不到则返回 end。和 find(…) 相反,count(begin, end, element) 返回一个元素在容器或容器的某个范围内出现的次数。

特别建议

在编写程序的过程中,模板列表能简化代码的阅读。

typedef vector<int> vi;
typedef vector<vi> vii;
typedef pair<int, int> ii;
#define sz(a) int(a.size()) //求对象a的大小
#define pb push_back
#define all(c) c.begin(),c.end()  //注意,all(c)后无括号 
#define present(c,x) ((c).find(x) != (c).end())  //元素x存在与c中,用于set,map等
#define cpresent(c,x) (find(all(c),x) != (c).end())  //通用算法find,适用于全部容器,时间复杂度O(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值