set的使用
________________________________________________________________________________________________________________
1.关于set
C++ STL 之所以得到广泛的赞誉,STL封装了许多复杂的数据结构算法和大量常用数据结构操作。vector封装数组,list封装了链表,map和set封装了二叉树等
关于 set是STL中一种标准关联容器。它底层使用平衡的搜索树——红黑树实现,也称RB树(Red-Black Tree)。插入删除操作时仅仅需要指针操作节点即可完成,不涉及到内存移动和拷贝,所以效率比较高。
set 的特点:
1.set中每个元素的值都唯一,即 无重复元素
2.set能根据元素的值默认从小到大 排序 (可以通过自定义函数更改排序方式)
如果需要集合中的元素允许重复那么可以使用multiset。
2.set 容器的创建
#include <iostream>
#include <set>
#include <functional>
using namespace std;
set<int> s;
int main(){
set<int > seta; //默认是小于比较器less<int>(即默认 从小到大排序)的set
set<int, greater<int> > setb; //创建一个(从大到小排序)的set,需包含头文件functional
int a[5] = {1,2,3,4,5};
set<int > setc(a,a+5); //数组a初始化一个set;
set<int > setd(setc.begin(),setc.end()); //setc初始化一个set
//上述两例均为区间初始化
set<int > sete(setd); //拷贝构造创建set
return 0;
}
3. set 的常用函数
________________________________________________________________________________________________________________
使用时注意包含头文件<set>
s.begin() 返回一个迭代器,返回的值为set容器的第一个元素
s.end() 返回一个迭代器,返回的值为set容器的最后一个元素
s.clear() 删除set容器中的所有的元素
s.empty() 判断set容器是否为空
s.insert() 插入一个元素
s.erase() 删除一个元素
s.size() 返回当前set容器中的元素个数
s.count() 用来查找set中某个某个键值出现的次数。
因为一个键值在set只可能出现0或1次,
可以用来判断某一键值是否在set出现过了(
可以用来判断输入的数据是否重复读入)
s.find() 返回给定值的定位器,如果没找到则返回end()
3.1 insert 插入
- pair<iterator,bool> insert(const value_type& __x);
//直接插入元素- iterator insert(iterator __position, const value_type& __x);
// 从定位器某位置插入- void insert(_InputIterator __first, _InputIterator __last)
//将一段区间 插入
#include <iostream>
#include <set>
#include <bits/stdc++.h>
using namespace std;
int cnt=0;
int main(){
set<int > s1;
set<int > s2;
//pair<iterator,bool> insert(const value_type& __x);
s1.insert(10);
s1.insert(10);
s1.insert(12);
s1.insert(13);
s1.insert(9);
cout << "Test output :" << ++cnt << ":" << endl;
set<int>::iterator it;
for(it = s1.begin(); it!=s1.end(); it++){
cout<<*it<<" ";
}
cout<<endl;
//--------------------------------------------------------------------------------------------------------------------------------------------
//iterator insert(iterator __position, const value_type& __x);
cout << "Test output :" << ++cnt << ":" << endl;
s1.insert(s1.begin(), 2);
for(it = s1.begin(); it!=s1.end(); it++){ //自动排序元素
cout<<*it<<" ";
}
cout<<endl;
//-------------------------------------------------------------------------------------------------------------------------------------------
//template<class _InputIterator>
//void insert(_InputIterator __first, _InputIterator __last)
int a[4] = {3,12,13,14};
s1.insert(a,a+4); //将区间[a, a+4]里的元素插入容器
cout << "Test output :" << ++cnt << ":" << endl;
for(it = s1.begin(); it!=s1.end(); it++){ //自动排序元素
cout<<*it<<" ";
}
cout<<endl;
s2.insert(1);
s2.insert(s1.begin(), s1.end());
cout << "Test output :" << ++cnt << ":" << endl;
for(it = s2.begin(); it!=s2.end(); it++){ //自动排序元素
cout<<*it<<" ";
}
cout<<endl;
return 0;
}
/* 结果:
Test output :1:
9 10 12 13
Test output :2:
2 9 10 12 13
Test output :3:
2 3 9 10 12 13 14
Test output :4:
1 2 3 9 10 12 13 14
*/
3.2 erase 删除
- erase(iterator) , 删除定位器iterator指向的值
- erase(first,second), 删除定位器first和second之间的值 ,左闭右开[ l, r)
- erase(key_value) , 删除键值key_value的值
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> s;
set<int>::iterator it;
for(int i = 1 ; i <= 10 ; i++)
{
s.insert(i);
cout << i << " " ;
}
cout << endl;
//------------------------------------------------------------------------------------------------------------------------------------------
// erase(iterator) 删除定位器iterator指向的值
it = s.begin(); // 删除第一个值
s.erase(s.begin());
cout << "第一个值删除之后 :" << endl;
for(it = s.begin() ; it != s.end() ; ++it)
{
cout<<*it<<" ";
}
cout << endl;
//-------------------------------------------------------------------------------------------------------------------------------------------
//erase(first,second), 删除定位器first和second之间的值,左闭右开[ l, r)
s.erase(++s.begin(),--s.end());
cout << "第二种删除 从第二个到 倒数第二个区间中的元素 之后 :" << endl;
for(it= s.begin() ; it != s.end() ; it++)
{
cout<<*it<<" ";
}
cout << endl;
//-----------------------------------------------------------------------------------------------------------------------------------------
s.erase(10);
cout << "第三次删除的是: 10" << endl;
for(it = s.begin() ; it != s.end() ; it++)
{
cout<<*it<<" ";
}
cout << endl;
return 0;
}
/* 结果是:
1 2 3 4 5 6 7 8 9 10
第一个值删除之后 :
2 3 4 5 6 7 8 9 10
第二种删除 从第二个到 倒数第二个区间中的元素 之后 :
2 10
第三次删除的是: 8
2
*/
3.3 find() 函数的使用
find() ,返回给定值的定位器,如果容器中不存在该元素,返回值等于end()
end()返回指向最后一个元素的下一个地址,存放的是当前容器的大小
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> s;
set<int>::iterator it;
for(int i = 1 ; i <= 10 ; i++)
{
s.insert(i);
cout << i << " " ;
}
cout << endl;
it=s.find(2); cout<<*it<<endl;
it=s.find(11); cout<<*it<<endl;
it=s.end(); cout<<*it<<endl;
return 0;
}
/* 结果为:
1 2 3 4 5 6 7 8 9 10
2
10
10
*/
3.4 lower_bound 和upper_bound
注意 * 号 的使用
lower_bound(key_value) ,返回第一个大于等于key_value的定位器
upper_bound(key_value),返回最后一个大于key_value的定位器
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> s;
set<int>::iterator it;
for(int i = 1 ; i <= 10 ; i++)
{
s.insert(i);
cout << i << " " ;
}
cout << endl;
cout << "lower_bound & upper_bound test:" << endl;
cout << "第一个大于或等于3的元素: " << *s.lower_bound(3) << endl;
cout << "第一个大于3的元素: " <<*s.upper_bound(3) << endl;
cout<<"\n"<<endl;
cout << "第一个大于或等于6的元素: " << *s.lower_bound(6) << endl;
cout << "第一个大于6的元素: " <<*s.upper_bound(6) << endl;
return 0;
}
/* 结果为:
1 2 3 4 5 6 7 8 9 10
lower_bound & upper_bound test:
第一个大于或等于3的元素: 3
第一个大于3的元素: 4
第一个大于或等于6的元素: 6
第一个大于6的元素: 7
*/
3.5 count() 的 使用
计算容器中某个元素的 出现次数
由于set容器的无重复元素的特性 返回值只有 0 或1
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> s;
if(!s.count(1))
{
s.insert(1);
}
else
{
cout<< "1 在容器中 "<<endl;
}
if(s.count(1))
{
cout<< "1 在容器中 "<<endl;
}
return 0;
}
/* 结果为:
1 在容器中
*/
4. 自定义比较函数
(1)元素不是结构体:
例:
//自定义比较函数myComp,重载“()”操作符
struct myComp
{
bool operator()(const your_type &a,const your_type &b)
{
return a.data > b.data;
}
};
set<int,myComp>s;
set<int,myComp>::iterator it;
(2)如果元素是结构体,可以直接将比较函数写在结构体内。
例:
struct Info
{
string name;
float score;
//重载“<”操作符,自定义排序规则
bool operator < (const Info &a) const
{
//按score从大到小排列
return a.score<score;
}
};
set<Info> s;
set<Info>::iterator it;
5. set 拓展使用
set 与 pair<int ,int > 的结合, 或与 stu 结构体 都实现了
(x,y)的二元组 优先 按x 从小到大排序, x相同时, 按y 从小到大排序
但在 set< pair<int,int > >s; 排序 为默认顺序
set< Stu > s1; 排序 为 结构体中自己 构造的排序
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct Stu
{
int x;
int y;
//重载“<”操作符,自定义排序规则
bool operator < (const Stu &a) const
{
//按y从大到小排列
if(a.x!=x)
return x<a.x;
else
return y<a.y;
}
};
int main()
{
set< pair<int,int > >s;
s.insert({10,10});
s.insert({8,20});
s.insert({20,6});
s.insert({8,6});
set< pair<int,int > > :: iterator it ;
for(it=s.begin(); it!=s.end(); it++)
{
cout<<it->first <<" "<<it->second<<endl;
}
cout<<"\n\n";
//----------------------------------------------------------------------
set< Stu > s1;
s1.insert({10,10});
s1.insert({8,20});
s1.insert({20,6});
s1.insert({8,6});
set< Stu > :: iterator it1;
for(it1=s1.begin(); it1!=s1.end(); it1++)
{
cout<<it1->x<<" "<<it1->y<<endl;
}
return 0;
}
8 6
8 20
10 10
20 6
8 6
8 20
10 10
20 6