在一些问题中经常需要用到set,set的最主要作用是自动去重按升序排序。
set翻译为集合,是一个内部自动有序且不含重复元素的容器。在出现需要去掉重复元素的情况,而且有可能因这些元素比较大或者类型不是int型而不能直接开散列表,在这种情况下就可以用set来保留元素本身而不考虑它的个数。当然,上面说的情况也可以通过再开一个数组进行下标和元素的对应来解决,但是set提供了更为直观的接口,并且加入set之后可以实现自动排序,因此熟练使用set可以在做某些题时减少思维量。
要使用set,需要添加set头文件,即#include<set>。除此之外,还需要在头文件下面加上一句:“ using namespace std;"。
1.set的定义:
(1)一维:
set<typename> name;
set<int> name;//int整数类型
set<node> name;//node结构体类型
set<vector<int> > name;//vector标准容器类型,记得加空格
typename可以是任何的基本类型,也可以是STL标准容器(如果typename也是一个STL容器,定义的时候要记得在>>符号之间加上空格,防止编译器将其视为移位运算符)。
(2)二维:
set<typename> Arrayname[arraySize];//一维长度是固定的,二维每一个都是set
set<set<int> > name;//一维、二维每一个都是set
2.set容器内元素的访问:
set只能通过迭代器(iterator)访问:
set<typename>::iterator it;
这样就得到了迭代器it,并且可以通过*it来访问set里面的元素,但是不能像vector和string一样使用*(it+i)来访问元素。
下面定义一个set并且通过迭代器访问:
程序代码:
#include<cstdio>
#include<set>
using namespace std;
int main(){
set<int> st;
st.insert(3);//insert(x)将x插入set中
st.insert(5);//insert(x)将x插入set中
st.insert(3);//insert(x)将x插入set中
st.insert(2);//insert(x)将x插入set中
//注意,不支持it<st.end()的写法
for(set<int>::iterator it = st.begin(); it!=st.end(); it++) {
printf("%d ",*it);
}
return 0;
}
运行结果:
可以发现,set内的元素自动递增排序,且自动去除了重复元素。
3.set常用函数实例解析:
(1)insert()
函数作用:insert(x)可将x插入set容器中,并自动递增排序和去重,时间复杂度为O(logN),其中N为set内的元素个数。示例见“2.set容器内元素的访问”。
(2)find()
函数作用:find(value)返回set中对应值为value的迭代器,时间复杂度为O(logN),N为set内的元素个数。
程序代码:
#include<cstdio>
#include<set>
using namespace std;
int main(){
set<int> st;
for(int i=1;i<=3;i++){
st.insert(i);
}
set<int>::iterator it = st.find(2); //在set中查找2,返回其迭代器
printf("%d\n",*it);
//以上两句也可以直接写成printf("%d\n",*(st.find(2));
return 0;
}
运行结果:
(3)size()
函数作用:size()获取set中元素的个数,时间复杂度为O(1)。
程序代码:
#include<cstdio>
#include<set>
using namespace std;
int main(){
set<int> st;
for(int i=1;i<=5;i++) {
st.insert(i);
}
printf("%d\n",st.size());
return 0;
}
运行结果:
(4)clear()
函数作用:clear()清空set中的所有元素,时间复杂度为O(N),其中N为set中元素的个数。
程序代码:
#include<cstdio>
#include<set>
using namespace std;
int main(){
set<int> st;
for(int i=1;i<=5;i++) {
st.insert(i);
}
printf("原元素个数=%d\n",st.size());
st.clear();
printf("原元素个数=%d\n",st.size());
return 0;
}
运行结果:
(5)erase()
函数作用:erase()两种用法:删除单个元素和删除一个区间内的所有元素。
删除单个元素:
- st.erase(it),it为所删除元素的迭代器。时间复杂度O(1)。
程序代码:
#include<cstdio>
#include<set>
using namespace std;
int main(){
set<int> st;
st.insert(100);//insert(x)将x插入set中
st.insert(200);//insert(x)将x插入set中
st.insert(300);//insert(x)将x插入set中
st.insert(400);//insert(x)将x插入set中
//注意,不支持it<st.end()的写法
st.erase(st.find(300)); //利用find()函数找到100,然后用erase删除它
for(set<int>::iterator it = st.begin(); it!=st.end(); it++) {
printf("%d ",*it);
}
return 0;
}
运行结果:
-
st.erase(value),value为所需删除元素的值,时间复杂度为O(logN),N为set内的元素。
#include<cstdio>
#include<set>
using namespace std;
int main(){
set<int> st;
st.insert(100);//insert(x)将x插入set中
st.insert(200);//insert(x)将x插入set中
st.insert(300);//insert(x)将x插入set中
st.insert(400);//insert(x)将x插入set中
//注意,不支持it<st.end()的写法
st.erase(300); //删除值为300 的元素
for(set<int>::iterator it = st.begin(); it!=st.end(); it++) {
printf("%d ",*it);
}
return 0;
}
删除一个区间内的所有元素:
st.erase(first,last)可以删除一个区间的所有元素,其中first为所需删除区间的其实迭代器,而last为所需删除的区间末尾迭代器的下一个地址,也即为删除[first,last)。时间复杂度为O(last-first)。
程序代码:
#include<cstdio>
#include<set>
using namespace std;
int main(){
set<int> st;
st.insert(100);//insert(x)将x插入set中
st.insert(200);//insert(x)将x插入set中
st.insert(300);//insert(x)将x插入set中
st.insert(400);//insert(x)将x插入set中
//注意,不支持it<st.end()的写法
st.erase(st.find(200),st.end()); //利用find()函数找到100,然后用erase删除它和其之后的所有
for(set<int>::iterator it = st.begin(); it!=st.end(); it++) {
printf("%d ",*it);
}
return 0;
}
运行结果: