STL nb!

These violent delights have violent ends.

And in their triumph die, like fire and powder,

Which, as they kiss, consume.

All Things About STL

大家好,我是废话 快速了解STL

STL是Standard Template Library的简称,中文名标准模板库,惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的。从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件。STL现在是C++的一部分,因此不用安装额外的库文件。


STL可分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分。(引自百度百科。一堆废话。

STL之Stack(堆栈)

堆栈是一个线性表,插入和删除只在表的一端进行。这一端称为栈顶(Stack Top),另一端则为栈底(Stack Bottom)。堆栈的元素插入称为入栈,元素的删除称为出栈。由于元素的入栈和出栈总在栈顶进行,因此,堆栈是一个后进先出(Last In First Out)表,即 LIFO 表。


C++ STL 的堆栈泛化是直接通过现有的序列容器来实现的,默认使用双端队列deque的数据结构,当然,可以采用其他线性结构(vector 或 list等),只要提供堆栈的入栈、出栈、栈顶元素访问和判断是否为空的操作即可。由于堆栈的底层使用的是其他容器,因此,堆栈可看做是一种适配器,将一种容器转换为另一种容器(堆栈容器)。


为了严格遵循堆栈的数据后进先出原则,stack 不提供元素的任何迭代器操作,因此,stack 容器也就不会向外部提供可用的前向或反向迭代器类型。


stack堆栈容器的C++标准头文件为 stack ,必须用宏语句 “#include “ 包含进来,才可对 stack 堆栈的程序进行编译。

Stack的成员函数

  • empty() 堆栈为空则返回真

  • pop() 移除栈顶元素

  • push() 在栈顶增加元素

  • size() 返回栈中元素数目

  • top() 返回栈顶元素

STL之queue(队列)

先进先出(FIFO),即插入和删除操作分别在位的不同端。插入元素的那一端为队尾,删除元素的那一端为队首。

queue的成员函数

  • back() 返回最后一个元素

  • empty() 如果队列空则返回真

  • front() 返回第一个元素

  • pop() 删除第一个元素

  • push() 在末尾加入一个元素

  • size() 返回队列中元素的个数

STL之priority queue(优先队列)

优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素。但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似于给队列里的元素进行了由大到小的顺序排序。元素的比较规则默认按元素值由大到小排序,可以重载“<”操作符来重新定义比较规则。

priority queue的成员函数

基本操作:

  • empty()    如果队列为空,则返回真

  • pop()    删除对顶元素,删除第一个元素

  • push()    加入一个元素

  • size()     返回优先队列中拥有的元素个数

  • top()     返回优先队列对顶元素,返回优先队列中有最高优先级的元素

在默认的优先队列中,优先级高的先出队。在默认的int型中先出队的为较大的数。

自定义优先级:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//定义结构,使用运算符重载,自定义优先级1 
struct cmp1
{
bool operator ()(int &a,int &b)
{
return a>b;//最小值优先
}
};
struct cmp2
{
bool operator ()(int &a,int &b)
{
return a<b;//最大值优先
}
};
//定义结构,使用运算符重载,自定义优先级2
struct number1
{
int x;
bool operator < (const number1 &a) const
{
return x>a.x;//最小值优先
}
};
struct number2
{
int x;
bool operator < (const number2 &a) const
{
return x<a.x;//最大值优先
}
};

priority_queue<int>que;//采用默认优先级构造队列

priority_queue<int,vector<int>,cmp1>que1;//最小值优先
riority_queue<int,vector<int>,cmp2>que2;//最大值优先

priority_queue<int,vector<int>,greater<int> >que3;//注意“>>”会被认为错误,这是右移运算符,所以这里用空格号隔开
priority_queue<int,vector<int>,less<int> >que4;//最大值优先

priority_queue<number1>que5;
priority_queue<number2>que6;

在优先队列中使用结构体的若干小结

以结构体Time为例:

1
2
3
4
struct Time
{
int start, end;
};

使用优先队列时,如果需要对Time中的start从小到大排序,有两种方法:

1
priority_queue<Time> pq;

一.在结构体外重载结构体小于运算符:

1
2
3
4
5
bool operator <(const Time& a,const Time& b)
{
return a.start > b.start;
}
//这里以大于重载小于是因为默认情况下,优先队列是以大的作为队首,这样一反,就可以再默认情况下使得小的作为队首

二.直接在结构体中重载小于运算符:

1
2
3
4
5
6
7
8
struct Time
{
int start, end;
bool operator < (const Time& t)const
{
return start > t.start;
}
};

实质上来说是一样的。。。。

另外要注意的是:参数列表中的const不能省略,否则报错~~

STL之deque(双端队列)

deque与vector非常相似,不仅可以在尾部插入和删除元素,还可以在头部插入和删除。不过当考虑到容器元素的内存分配策略和操作性能时,deque相对vector较为有优势。

deque的成员函数

  • [ ]:用来访问双向队列中单个的元素。

  • front():返回第一个元素的引用。

  • back():返回最后一个元素的引用。

  • push_front(x):把元素x插入到双向队列的头部。

  • pop_front():弹出双向队列的第一个元素。

  • push_back(x):把元素x插入到双向队列的尾部。

  • pop_back():弹出双向队列的最后一个元素。

STL之vector(引自@博客园_清水汪汪)

  1. vector是表示可变大小数组的序列容器。
  2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
  3. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
  4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
  5. 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
  6. 与其它动态序列容器相比(deques, lists and forward_lists), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起lists和forward_lists统一的迭代器和引用更好。

vector的成员函数

  1. 容量
  • 向量大小: vec.size();
  • 向量最大容量: vec.max_size();
  • 更改向量大小: vec.resize();
  • 向量真实大小: vec.capacity();
  • 向量判空: vec.empty();
  • 减少向量大小到满足元素所占存储空间的大小: vec.shrink_to_fit(); //shrink_to_fit
  1. 修改
  • 多个元素赋值: vec.assign(); //类似于初始化时用数组进行赋值
  • 末尾添加元素: vec.push_back();
  • 末尾删除元素: vec.pop_back();
  • 任意位置插入元素: vec.insert();
  • 任意位置删除元素: vec.erase();
  • 交换两个向量的元素: vec.swap();
  • 清空向量元素: vec.clear();
  1. 迭代器
  • 开始指针:vec.begin();
  • 末尾指针:vec.end(); //指向最后一个元素的下一个位置
  • 指向常量的开始指针: vec.cbegin(); //意思就是不能通过这个指针来修改所指的内容,但还是可以通过其他方式修改的,而且指针也是可以移动的。
  • 指向常量的末尾指针: vec.cend();
  1. 元素的访问
  • 下标访问: vec[1]; //并不会检查是否越界
  • at方法访问: vec.at(1); //以上两者的区别就是at会检查是否越界,是则抛出out of range异常
  • 访问第一个元素: vec.front();
  • 访问最后一个元素: vec.back();
  • 返回一个指针: int* p = vec.data(); //可行的原因在于vector在内存中就是一个连续存储的数组,所以可以返回一个指针指向这个数组。这是是C++11的特性。
  1. 算法
  • 遍历元素

    1
    2
    3
    4
    5
    6
    7
    8
    vector<int>::iterator it;
    for (it = vec.begin(); it != vec.end(); it++)
    cout << *it << endl;
    //或者
    for (size_t i = 0; i < vec.size(); i++)
    {
    cout << vec.at(i) << endl;
    }
  • 元素翻转

    1
    2
    #include <algorithm>
    reverse(vec.begin(), vec.end());
  • 元素排序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <algorithm>
    sort(vec.begin(), vec.end());
    //采用的是从小到大的排序
    //如果想从大到小排序,可以采用上面反转函数,也可以采用下面方法:
    bool Comp(const int& a, const int& b)
    {
    return a > b;
    }
    sort(vec.begin(), vec.end(), Comp);

STL之vector,deque对比(引自@开源中国_爱吃冰红茶)

vector,deuqe之对比:

  1. 随机访问速度:vector > deque。

  2. deque性能损失比vector高几个数量级:因为deque首次插入一个元素时,会默认动态分配512字节空间,当这512字节空间用完后,它会再动态分配自己另外的512字节空间,然后虚拟地连在一起。deque的这种设计使得它具有比vector复杂得多的架构、算法和迭代器设计,也使得性能损失比vector高!

  3. 在插入删除操作时,deque由于vector:对于vector而言,由于其是一端开口,所以在尾部插入耗费固定的时间,而在头部进行插入时,耗费的时间与vector的大小成正比,vector越大,耗费的时间越多。而对于deque,不管插入删除操作是在头部还是尾部进行,算法的效率是固定的。

可以得到,在vector和deque进行插入删除时,deque的效率是高于vector的。当都是在末尾进行插入时,vector和deque的差别不大,但是在对头部进行插入时,差距十分明显。

总结一下:当进行插入删除时候,选择deque,当进行顺序访问时,选择vector。

STL之list

List是stl实现的双向链表,与向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢。使用时需要添加头文件。

list的成员函数

  • Lst1.assign() :给list赋值

  • Lst1.back() :返回最后一个元素

  • Lst1.begin() :返回指向第一个元素的迭代器

  • Lst1.clear() :删除所有元素

  • Lst1.empty() :如果list是空的则返回true

  • Lst1.end() :返回末尾的迭代器

  • Lst1.erase() :删除一个元素

  • Lst1.front() :返回第一个元素

  • Lst1.get_allocator() :返回list的配置器

  • Lst1.insert() :插入一个元素到list中

  • Lst1.max_size() :返回list能容纳的最大元素数量

  • Lst1.merge() :合并两个list

  • Lst1.pop_back() :删除最后一个元素

  • Lst1.pop_front() :删除第一个元素

  • Lst1.push_back() :在list的末尾添加一个元素

  • Lst1.push_front() :在list的头部添加一个元素

  • Lst1.rbegin() :返回指向第一个元素的逆向迭代器

  • Lst1.remove() :从list删除元素

  • Lst1.remove_if() :按指定条件删除元素

  • Lst1.rend() :指向list末尾的逆向迭代器

  • Lst1.resize() :改变list的大小

  • Lst1.reverse() :把list的元素倒转

  • Lst1.size() :返回list中的元素个数

  • Lst1.sort() :给list排序

  • Lst1.splice() :合并两个list

  • Lst1.swap() :交换两个list

  • Lst1.unique() :删除list中重复的元素

  • 遍历List

    1
    2
    3
    4
    5
    for(list<int>::const_iteratoriter = lst1.begin();iter != lst1.end();iter++)
    {
    cout<<*iter;
    }
    cout<<endl;

STL之map

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。

容器中元素的访问

  1. 下标访问

    和访问数组一样。map中键是唯一的

  2. 迭代器访问

    map< typename1 , typename2 >::iterator it;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
#include<map>

using namespace std;

int main()
{
map<char,int> mp;
mp['a']=5;
mp['b']=10;
mp['d']=40;
mp['c']=20;
mp['c']=30;//20被覆盖
printf("%d\n",mp['c']);
for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++)
{
printf("%c %d\n",it->first,it->second);
//it->first:当前映射的键,it->second:当前映射的值
}
//a 5
//b 10
//c 30
//d 40
//map会以键从小到大的顺序自动排序。map内部是使用红黑树实现的,set内部也是。
//建立映射的时候,会自动实现从小到大的排序功能
return 0;
}

map的成员函数

  1. find()
  • find(key):返回键为key的映射,时间复杂度为O(logN)
  1. erase()
  • 删除单个元素
    • mp.erase(it):it为需要删除的元素的迭代器。时间复杂度为O(1)
    • mp.erase(key):key为删除元素的键,时间复杂度为O(logN)
  • 删除区间内的元素
    • 左闭右开[start,end)
  1. size()
  2. clear()
  • 用来清空map,复杂度为O(N)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    #include<stdio.h>
    #include<map>

    using namespace std;

    int main()
    {
    map<char,int> mp;
    mp['a']=5;
    mp['b']=10;
    mp['d']=40;
    mp['c']=20;
    mp['c']=30;//20被覆盖
    printf("%d\n",mp['c']);//30

    mp.erase('b');//删除键为b的映射,也就是b 10
    for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++)
    {
    printf("%c %d\n",it->first,it->second);
    }
    //a 5
    //c 30
    //d 40
    map<char,int>::iterator it=mp.find("a");
    mp.erase(it);//删除a 5
    for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++)
    {
    printf("%c %d\n",it->first,it->second);
    }
    //c 30
    //d 40
    mp['e']=50;
    mp['f']=60;
    map<char,int>::iterator it=mp.find("d");
    mp.erase(it,mp.end());//删除区间, d 40 e 50
    return 0;
    }

map排序

  1. C++ STL中Map的按Key排序

    其实,为了实现快速查找,map内部本身就是按序存储的(比如红黑树)。在我们插入< key, value>键值对时,就会按照key的大小顺序进行存储。这也是作为key的类型必须能够进行 < 运算比较的原因。现在我们用string类型作为key,因此,我们的存储就是按学生姓名的字典排序储存的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<map>
#include<string>
#include<iostream>
using namespace std;

typedef pair<string, int> PAIR;

ostream& operator<<(ostream& out, const PAIR& p)
{
return out << p.first << "\t" << p.second;
}

int main()
{
map<string, int> name_score_map;
name_score_map["LiMin"] = 90;
name_score_map["ZiLinMi"] = 79;
name_score_map["BoB"] = 92;
name_score_map.insert(make_pair("Bing",99));
name_score_map.insert(make_pair("Albert",86));
for (map<string, int>::iterator iter = name_score_map.begin();iter != name_score_map.end();++iter)
{
cout << *iter << endl;
}
return 0;
}

现在知道如何为map指定Compare类了,如果我们想自己写一个compare的类,让map按照我们想要的顺序来存储,比如,按照学生姓名的长短排序进行存储,那该怎么做呢?


其实很简单,只要我们自己写一个函数对象,实现想要的逻辑,定义map的时候把Compare指定为我们自己编写的这个就ok啦。

1
2
3
4
5
6
7
struct CmpByKeyLength 
{
bool operator()(const string& k1, const string& k2)
{
return k1.length() < k2.length();
}
};
  1. C++ STL中Map的按Value排序

    虽然不能直接用sort对map进行排序,那么我们可不可以迂回一下,把map中的元素放到序列容器(如vector)中,然后再对这些元素进行排序呢?这个想法看似是可行的。要对序列容器中的元素进行排序,也有个必要条件:就是容器中的元素必须是可比较的,也就是实现了< 操作的。


    令人兴奋的是,sort算法和map一样,也可以让我们指定元素间如何进行比较,即指定Compare。需要注意的是,map是在定义时指定的,所以传参的时候直接传入函数对象的类名,就像指定key和value时指定的类型名一样;sort算法是在调用时指定的,需要传入一个对象,当然这个也简单,类名()就会调用构造函数生成对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main() 
{
map<string, int> name_score_map;
name_score_map["LiMin"] = 90;
name_score_map["ZiLinMi"] = 79;
name_score_map["BoB"] = 92;
name_score_map.insert(make_pair("Bing",99));
name_score_map.insert(make_pair("Albert",86));
//把map中元素转存到vector中
vector<PAIR> name_score_vec(name_score_map.begin(), name_score_map.end());
sort(name_score_vec.begin(), name_score_vec.end(), CmpByValue());
// sort(name_score_vec.begin(), name_score_vec.end(), cmp_by_value);
for (int i = 0; i != name_score_vec.size(); ++i)
{
cout << name_score_vec[i] << endl;
}
return 0;
}

STL之hash_map

hash_map的用法和map是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。虽然对外部提供的函数和数据类型是一致的,但是其底层实现是完全不同的,map底层的数据结构是rb_tree而,hansh_map却是哈希表来实现的。

  • map与hash_map

    总体来说,hash_map 查找速度会比map快,而且查找速度基本和数据量大小无关,属于常数级别;而map的查找速度是log(n)级别。hash还有hash函数的耗时。当有100w条记录的时候,map也只需要20次的比较,200w也只需要21次的比较!所以并不一定常数就比log(n) 小!


    hash_map对空间的要求要比map高很多,所以是以空间换时间的方法,而且,hash_map如果hash函数和hash因子选择不好的话,也许不会达到你要的效果,所以至于用map,还是hash_map,从3个方面来权衡: 查找速度, 数据量, 内存使用,还有一个就是你的经验!没有特别的标准


    另外可以通过重写 hash_compair仿函数,更改里面关于桶数量的定义,如果取值合适,也可以得到更优的性能。而且如果你的数据是自定义的类型,必须要重写这个仿函数。可以模仿原来的写法,所有的成员函数,成员变量一个不能少!

STL之multimap

标准库还定义了一个 multimap 容器,它与 map 类似,所不同的是它允许重复键。这个属性使得 multimap 比预想的要更有用:比如在电话簿中相同的人可以有两个以上电话号码,文件系统中可以将多个符号链接映射到相同的物理文件,或DNS服务器可以将几个URLs映射到相同的IP地址。

multimap的成员函数

  • begin() :返回指向第一个元素的迭代器

  • clear() :删除所有元素

  • count() :返回一个元素出现的次数

  • empty() :如果multimap为空则返回真

  • end() :返回一个指向multimap末尾的迭代器

  • equal_range() :返回指向元素的key为指定值的迭代器对

  • erase() :删除元素

  • find() :查找元素

  • get_allocator() :返回multimap的配置器

  • insert() :插入元素

  • key_comp() :返回比较key的函数

  • lower_bound() :返回键值>=给定元素的第一个位置

  • max_size() :返回可以容纳的最大元素个数

  • rbegin() :返回一个指向mulitmap尾部的逆向迭代器

  • rend() :返回一个指向multimap头部的逆向迭代器

  • size() :返回multimap中元素的个数

  • swap() :交换两个multimaps

  • upper_bound() :返回键值>给定元素的第一个位置

  • value_comp() :返回比较元素value的函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    //multimap允许重复的键值插入容器
    // **********************************************************
    // * pair只包含一对数值:pair<int,char> *
    // * map是一个集合类型,永远保持排好序的, *
    // * map每一个成员就是一个pair,例如:map<int,char> *
    // * map的insert()可以把一个pair对象作为map的参数,例如map<p> *
    // ***********************************************************
    #include<map>
    #include<iostream>
    using namespace std;
    int main(void)
    {
    multimap<int,char*> m;
    //multimap的插入只能用insert()不能用数组
    m.insert(pair<int,char*>(1,"apple"));
    m.insert(pair<int,char*>(1,"pear"));
    //apple和pear的价钱完全有可能是一样的
    m.insert(pair<int,char*>(2,"banana"));
    //multimap的遍历只能用迭代器方式不能用数组
    cout<<"***************************************"<<endl;
    multimap<int,char*>::iterator i,iend;
    iend=m.end();
    for(i=m.begin();i!=iend;i++)
    {
    cout<<(*i).second<<"的价钱是"<<(*i).first<<"元/斤n";
    }
    cout<<"***************************************"<<endl;
    //元素的反相遍历
    multimap<int,char*>::reverse_iterator j,jend;
    jend=m.rend();
    for(j=m.rbegin();j!=jend;j++)
    {
    cout<<(*j).second<<"的价钱是"
    <<(*j).first<<"元/斤n";
    }
    cout<<"***************************************"<<endl;
    //元素的搜索find(),pair<iterator,iterator>equal_range(const key_type &k)const
    //和multiset的用法一样
    multimap<int,char*>::iterator s;
    s=m.find(1);//find()只要找到一个就行了,然后立即返回。
    cout<<(*s).second<<" "
    <<(*s).first<<endl;
    cout<<"键值等于1的元素个数是:"<<m.count(1)<<endl;
    cout<<"***************************************"<<endl;
    //删除 erase(),clear()
    m.erase(1);
    for(i=m.begin();i!=iend;i++)
    {
    cout<<(*i).second<<"的价钱是"
    <<(*i).first<<"元/斤n";
    }
    return 0;
    }
  • 遍历

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // 使用遍历器遍历:
    Iterator iter = map.entries().iterator();
    while(iter.hasNext())
    {
    Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>)iter.next();
    System.out.println(String.format("%d:%d", entry.getKey(),entry.getValue()));
    }
    //使用Key值遍历,key值可以得到一个全部键值的MultiSet或者是一个没有重复键值的KeySet
    Set<Integer> keys = map.keySet();
    for(int key:keys)
    {
    String result = String.format("%d:", key);
    Set<Integer> values = map.get(key);
    for(int value:values)
    {
    result= result+" "+value;
    }
    System.out.println(result);
    }

STL之set

set,顾名思义,就是数学上的集合——每个元素最多只出现一次,并且set中的元素已经从小到大排好序。

set的成员函数

  • begin() :返回set容器的第一个元素的地址

  • end() :返回set容器的最后一个元素地址

  • clear() :删除set容器中的所有的元素

  • empty() :判断set容器是否为空

  • max_size() :返回set容器可能包含的元素最大个数

  • size() :返回当前set容器中的元素个数

  • erase(it) :删除迭代器指针it处元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include <iostream>
    #include <set>

    using namespace std;

    int main()
    {
    set<int> s;
    s.insert(1);
    s.insert(2);
    s.insert(3);
    s.insert(1);
    cout<<"set 的 size 值为 :"<<s.size()<<endl;
    cout<<"set 的 maxsize的值为 :"<<s.max_size()<<endl;
    cout<<"set 中的第一个元素是 :"<<*s.begin()<<endl;
    cout<<"set 中的最后一个元素是:"<<*s.end()<<endl;
    s.clear();
    if(s.empty())
    {
    cout<<"set 为空 !!!"<<endl;
    }
    cout<<"set 的 size 值为 :"<<s.size()<<endl;
    cout<<"set 的 maxsize的值为 :"<<s.max_size()<<endl;
    return 0;
    }
  • count() :用来查找set中某个元素出现的次数。这个函数在set并不是很实用,因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了。

  • find(): 用来查找set中某个元素出现的位置。如果找到,就返回这个元素的迭代器,如果这个元素不存在,则返回 s.end() 。 (最后一个元素的下一个位置,s为set的变量名)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include <iostream>
    #include <set>

    using namespace std;

    int main()
    {
    set<int> s;
    set<int>::iterator it; //创建一个他对应的迭代器

    s.insert(1);
    s.insert(2);
    s.insert(3);
    s.insert(1);
    cout<<"set 中 1 出现的次数是 :"<<s.count(1)<<endl;
    cout<<"set 中 4 出现的次数是 :"<<s.count(4)<<endl;

    it1 = st1.find(4); //查找数据
    if (it1 != st1.end()) //如果找到就输出数据
    {
    cout << *it1 << endl;
    }

    return 0;
    }
  • 遍历

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    ##include <iostream>
    #include<set>
    using namespace std;


    int main()
    {
    set<int> s; //创建一个int类型的set

    s.insert(10); //插入数据
    s.insert(30);
    s.insert(20);
    s.insert(40);

    //遍历数据,用迭代器遍历数据
    for (set<int>::iterator it = s.begin(); it != s.end(); ++it)
    {
    cout << *it << endl;
    }
    //这里用到了set中的元素已经从小到大排好序的性质

    return 0;
    }
  • set+struct

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    #include<iostream>
    #include<set>
    #include<string>
    using namespace std;
    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.name = "Jack";
    info.score = 80;
    s.insert(info);
    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 : 99
    Jack : 80
    Steaven : 60
    */

最后更新: 2019年08月05日 09:44

原始链接: http://yisin.top/2019/03/16/All-Things-About-STL/

× 请我吃糖~
打赏二维码