集合(Set)是一种包含已排序对象的关联容器。 set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的数据结构,在插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,它不会插入相同键值的元素,而采取忽略处理。
平衡二叉树的检索使用中序遍历算法,检索效率高于vector、deque和list等容器。
对于set容器中的键值,不可直接去修改!应该先删除该键值,再插入新的键值。
set提供了集合的交并补运算。
头文件为#include <set>
1.创建set集合对象
set <Element> s;
Element容器中的数据类型(可以是int,double等系统自带的类型,也可以为自定义类型)
2.元素的插入和遍历
insert()插入元素
迭代器遍历
#include <iostream>
#include <set>
using namespace std;
int main()
{
set <int> s; //建立set容器
s.insert(6);//插入6
s.insert(1);//插入1
s.insert(9);//插入9
s.insert(1);//插入1
for(set<int>::iterator it = s.begin(); it != s.end(); it++)//定义前向迭代器遍历输出
{
printf("%d ",*it);
}
printf("\n");
for(set<int>::reverse_iterator rit = s.rbegin(); rit != s.rend(); rit++)//定义反向迭代器遍历输出
{
printf("%d ",*rit);
}
return 0;
}
2.元素的删除
erase()删除函数,删除某一个元素或者某一段。
#include <iostream>
#include <set>
using namespace std;
int main()
{
set <int> s; //建立set容器
s.insert(6);//插入6
s.insert(1);//插入1
s.insert(9);//插入9
for(set<int>::iterator it = s.begin(); it != s.end(); it++)//定义前向迭代器遍历输出
{
printf("%d ",*it);
}
s.erase(9);//删除9
printf("\n");
for(set<int>::iterator it = s.begin(); it != s.end(); it++)//定义前向迭代器遍历输出
{
printf("%d ",*it);
}
printf("\n");
return 0;
}
3.元素的检索
find()函数查找键值,查找到就返回迭代器位置,如果查找不到返回end位置的迭代器
count()函数判断某个元素是否存在
#include <iostream>
#include <set>
using namespace std;
int main()
{
set <int> s; //建立set容器
s.insert(6);//插入6
s.insert(1);//插入1
s.insert(9);//插入9
set<int>::iterator it;
it=s.find(6);//查找键值6,如果查找不到返回end位置的迭代器
if(it != s.end())//找到了
printf("%d\n",*it);
else
printf("not find it\n");
//查找元素999是否存在存在返回true不存在返回fasle
if(s.count(999))//找到了
printf("%d\n",*it);
else
printf("not find it\n");
return 0;
}
4.自定义比较函数
#include <iostream>
#include <set>
#include <functional>
using namespace std;
struct Node
{
int a,b;
bool operator < (const Node &A) const
{
return a > A.a;
}
};
set <Node> s; //自定义排序函数构造set
int main()
{
Node x;
x.a = 1,x.b = 39;
s.insert(x);
x.a = 2,x.b = 17;
s.insert(x);
x.a = 3,x.b = 28;
s.insert(x);
for(set<Node>::iterator it = s.begin(); it != s.end(); it++)
{
printf("%d %d\n",(*it).a,(*it).b);
}
return 0;
}
5.集合的交,并,补,差及对称差运算
这些运算在<algorithm>头文件中
假设有集合R,S。
并集:set_union(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R∪S
交集:set_intersection(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R∩S
差集:set_difference(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R-S
对称差:set_symmetric_difference(S.begin(), S.end(), R.begin(), R.end(), inserter(ans, ans.begin()));//R⊕S
假设全集U = R ∪ S,那么R对于U的补集为U - R。
#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
int main()
{
set<int> R, S, ans;
cout << "R:";
for (int i = 0; i <= 6; i++) { R.insert(i); cout << i << " "; }// 0 1 2 3 4 5 6
cout << endl;
cout << "S:";
for (int i = 4; i <= 10; i++) { S.insert(i); cout << i << " "; }// 4 5 6 7 8 9 10
cout << endl;
set_union(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R∪S
cout << "交:";
for (auto i: ans) cout << i << " ";
cout << endl; ans.clear();
set_intersection(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R∩S
cout << "并:";
for (auto i: ans) cout << i << " ";
cout << endl; ans.clear();
set_difference(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R-S
cout << "R-S:";
for (auto i: ans) cout << i << " ";
cout << endl; ans.clear();
set_difference(S.begin(), S.end(), R.begin(), R.end(), inserter(ans, ans.begin()));//S-R
cout << "S-R:";
for (auto i: ans) cout << i << " ";
cout << endl; ans.clear();
set_symmetric_difference(S.begin(), S.end(), R.begin(), R.end(), inserter(ans, ans.begin()));//R⊕S
cout << "对称差(环和):";
for (auto i: ans) cout << i << " ";
cout << endl; ans.clear();
return 0;
}
多重集合容器(multiset)
基本和set一样,但是这个允许插入重复的键值!因为包含重复元素,所以,在插入元素、删除元素、查找元素上较set有差别
1.插入元素
#include <iostream>
#include <set>
using namespace std;
int main()
{
multiset <int> ms; //建立multiset容器
ms.insert(6);//插入6
ms.insert(1);//插入1
ms.insert(9);//插入9
ms.insert(1);//插入1
for(multiset<int>::iterator it = ms.begin(); it != ms.end(); it++)//定义前向迭代器遍历输出
{
printf("%d ",*it);
}
printf("\n");
return 0;
}
2.删除元素
#include <iostream>
#include <set>
using namespace std;
int main()
{
multiset <string> ms; //建立multiset容器
ms.insert("666");//插入666
ms.insert("111");//插入111
ms.insert("abc");//插入abc
ms.insert("aaa");//插入aaa
ms.insert("111");//插入111
for(multiset<string>::iterator it = ms.begin(); it != ms.end(); it++)//定义前向迭代器遍历输出
{
cout<< *it <<endl;
}
printf("\n");
int n = ms.erase("111");//删除"111"所有元素,返回删除个数2
printf("删除元素个数为:%d\n",n);
for(multiset<string>::iterator it = ms.begin(); it != ms.end(); it++)//定义前向迭代器遍历输出
{
cout<< *it <<endl;
}
printf("\n");
return 0;
}
3.查找元素
返回符合要求的第一个元素的迭代器位置。他有lower_bound和upper_bound的两个函数。
#include <iostream>
#include <set>
using namespace std;
int main()
{
multiset <string> ms; //建立multiset容器
ms.insert("666");//插入666
ms.insert("111");//插入111
ms.insert("abc");//插入abc
ms.insert("aaa");//插入aaa
ms.insert("111");//插入111
multiset<string>::iterator it;
it=ms.find("111");//查找键值6,如果查找不到返回end位置的迭代器
if(it != ms.end())//找到了
cout << *it << endl;
else
printf("not find it\n");
it=ms.find("xyz");
if(it != ms.end())//找到了
cout << *it << endl;
else
printf("not find it\n");
it=ms.lower_bound("111");
if(it != ms.end())//找到了
cout << *it << endl;
else
printf("not find it\n");
return 0;
}
unordered_set
unordered_set是无序的,与set相比运行较快,内存占用较大。基本操作与set相同。
来源:oschina
链接:https://my.oschina.net/u/4386227/blog/3216481