1.集合的概念
集合,简称集,是数学中一个基本概念,也是集合论的主要研究对象。集合论的基本理论创立于19世纪,关于集合的最简单的说法就是在朴素集合论(最原始的集合论)中的定义,即集合是“确定的一堆东西”,集合里的“东西”则称为元素。现代的集合一般被定义为:由一个或多个确定的元素所构成的整体。
生活中的关于集合的例子很多:
-
北京海淀区中学的 105 班的同学,这就是一个集合。这个集合里面会有一堆同学,而且是非常明确的,每个同学都不一样。
-
广东中考的科目,这也是一个集合,按照目前的规定,包含了:语文、数学、英语、物理、化学、政治、历史、体育。
-
佛山市南海区的公交车路线,这也是一个集合,里面包含很多条路线。
按照数学上的概念,集合是没有顺序的,例如,{ 张三、李四、王五 } 这个集合其实等同于 { 王五、张三、李四 } 。所以,集合本身不解决成员出现的先收顺序问题。
但是,在信息学里面,我们常常要做意见事情就是检查一下某个东西是否在一个集合里面。如果这个集合内的成员是没有顺序的话,那么我们就要枚举每一个集合元素,才能知道某个东西是不是在集合里面。所以,计算机的算法里面额外引入了一些功能,那就是对集合的元素进行排序,那么检查集合成员的时候就可以基于二分法去检查,计算福大度就从 O(N) 降低为 O(ln N)。但是,我们需要知道,这仅仅是因为工程实现上的需要引入的额外功能,这个功能和数学里面讲的集合没有必然性。
STL 模板就就包含了集合这个容器。这个容器把几乎所有的集合功能都实现好了,我们只需要按照一定的格式和方法去运用就可以了。使用 STL 模板可以简化我们的代码,提升代码的效率,增强代码的可读性。
2.STL 的 set 容器
2.1 set 的定义
//语法
//set <数据类型> 集合实例名字;
set <int> a; // 创建 int 类型的集合 a
set <long long> b; // 创建 long long 类型的集合 a
set <string> c; // 创建 a 类型的集合 a
struct student{
int id;
string name;
operator < (student a){
return id<a.id;
};// 结构体之间需要能比较,才能排序。set 是有序容器,如果不能比较,就不能创建结构体的集合
}
set <student> e; // 创建结构体 student 的集合 e
2.2 set 的函数
2.2.1 insert
往集合内插入一个元素。假设集合内已经存在这个元素了,就会什么都不做(不会报错)
set <int> s;
s.insert(3);
s.insert(4);
s.insert(1);
s.insert(4); // 执行这句不会报错,但是因为之前就已经有了 4 ,所以 4 就不会重复插入了
2.2.2 begin() 和 end()
begin() 返回集合的第一个元素的指针。end()返回最后一个元素后面的指针(注意,因为是左闭右开,所以这个 end() 返回的指针不是有效数据。
2.2.3 rbegin() 和 rend()
和 begin()/end() 类似,只不过是反向的。rend() 返回集合最后一个元素的指针(不是空的),rbegin() 返回第一元素之前的指针(注意,因为才有左开右闭原则,所以 rbegin() 其实是空指针)。
2.2.4 find
通过 find 函数可以查找集合内是否存在一个元素。find 函数返回的是一个指针。如果找不到,返回的是空指针(就是 end() 了)。
set <int> s;
for(int i=1;i<100;i++)
s.insert(i);
set <int> :: iterator it; // 迭代器,其实是指针变量
it = s.find(5); // 查找 5 ,返回对应的元素的指针
cout<< *it; // it 指向的是 5,通过 * 运算,获得它的值,所以输出的是 5
it = s.find(500); // 查找500,集合里找不到,所以会得到 end();
if(it==s.end()) cout<<"集合里没有 500,找不到";
2.2.5 lower_bound() 和 upper_bound()
lower_bound 是大于等于
查找,lower_bound(a) 返回大于等于 a 的最小的那个元素。
lower_bound 是大于
查找,upper_bound(a) 返回大于 a 的最小的那个元素。
set <int> s;
s.insert(7);
s.insert(11);
s.insert(13);
s.insert(15);
s.insert(20);
set <int> :: iterator it; // 迭代器,其实是指针变量
it = s.lower_bound(13); // 找大于等于 13 的最小的那个数
cout<< *it <<endl; // 找到 13
it = s.upper_bound(13); // 找大于 13 的最小的那个数
cout<< *it <<endl; // 找到 15
it = s.upper_bound(25); // 找大于 25 的最小的那个数 ,找不到
// 所以 it 会等于 s.end()
2.2.6 clear()
清空整个集合(删除全部元素)
set <int> s;
s.insert(3);
s.insert(4);
s.insert(2);
s.clear(); // 集合清空
2.2.7 erase()
erase 是一个重载函数,输入的参数可以是一个值,也可以是一个指针(迭代器)。
#include<bits/stdc++.h>
using namespace std;
int main()
{
set <int> s;
s.insert(7);
s.insert(11);
s.insert(13);
s.insert(15);
s.insert(20);
set <int> :: iterator it; // 迭代器,其实是指针变量
s.erase(7);
it = s.find(13);
s.erase(it);
set <int> :: reverse_iterator it2; // 反向迭代器
for(it2=s.rbegin() ; it2!=s.rend(); it2++) // 从大到小输出 集合 元素
printf("%d ",*it2);
return 0;
}
后面我会讲下数学上的集合。