c++之Set和multiset容器
文章目录
前言
1、set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列。元素插入过程是按排序规则
插入,所以不能指定插入位置。
2、set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。
3、set不可以直接存取元素。(不可以使用at.(pos)与[]操作符)。
4、multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。
5、不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果希望修改一个元素值,必须先
删除原有的元素,再插入新的元素。
6、使用头文件set
一、这块在set、multiset容器中出现了红黑树,接下来解释一下
1、红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。
2、红黑树是一种特定类型的二叉树,它是在计算机科学中用来组织数据比如数字的块的一种结构。所有数据块都存储在节点中。这些节点中的某一个节点总是担当起始位置的功能,它不是任何节点的儿子,我们称之为根节点或根。它有最多两个"儿子",都是它连接到的其他节点。所有这些儿子都可以有自己的儿子,以此类推。这样根节点就有了把它连接到在树中任何其他节点的路径。
3、由于红黑树也是二叉查找树,它们当中每一个节点的比较值都必须大于或等于在它的左子树中的所有节点,并且小于或等于在它的右子树中的所有节点。这确保红黑树运作时能够快速的在树中查找给定的值
我们今天主要介绍用法,就不过多阐述啦,后面数据结构分栏里面会介绍更加详细
二、set用法
1.set的插入与迭代器
1.set.insert(elem); //在容器中插入元素。
2.set.begin(); //返回容器中第一个数据的迭代器。
3.set.end(); //返回容器中最后一个数据之后的迭代器。
4.set.rbegin(); //返回容器中倒数第一个元素的迭代器。
5.set.rend(); //返回容器中倒数最后一个元素的后面的迭代器。
2.Set集合的元素排序
1.set<int,less > setIntA; //该容器是按升序方式排列元素。
2.set<int,greater> setIntB; //该容器是按降序方式排列元素。
3.set 相当于 set<int,less>
set<int> setInt;
setInt.insert(3);
setInt.insert(1);
setInt.insert(5);
setInt.insert(2);
默认情况下 ,set遍历结果是1 2 3 5//从小到大
set<int,greater<int>> setIntB;
setIntB.insert(3);
setIntB.insert(1);
setIntB.insert(5);
setIntB.insert(2);
在这种情况下,set遍历结果是 5 3 2 1
抛出两个问题
1、less<>与greater<>是什么?
2、如果set<>不包含int类型,而是包含自定义类型,set容器如何排序?
解决上面两个问题的答案是容器的函数对象,也叫伪函数,又叫functor
3.函数对象functor的用法
1.尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象。
2.functor,翻译成函数对象,伪函数,算符,是重载了“()”操作符的普通类对象。从语法上讲,它与普通函数行为类似。
3.greater<>与less<>就是函数对象。
下面举出greater<int>的简易实现原理
struct greater
{
bool operator() (const int& iLeft, const int& iRight)
{
return (iLeft>iRight); //如果是实现less<int>的话,这边是写return (iLeft<iRight);从大到小
}
}
容器就是调用函数对象的operator()方法去比较两个值的大小。
struct less
{
bool operator() (const int& iLeft, const int& iRight)
{
return (iLeft<iRight); //如果是实现less<int>的话,这边是写return (iLeft<iRight);从小到大
}
}
案例:往set容器里面插入几个学生对象,按照年龄升序的办法进行排列
class student
{
public:
student(char *name,int age)
{
strcpy(this->name,name);
this->age=age;
}
public:
char name[64];
int age;
};
//仿函数
struct FuncStudent
{
bool operator()(const student &Left,const student &right)
{
if(Left.age<right.age)
return true;
else
return false;
}
}
void main()
{
student s1("s1",31);
student s2("s2",22);
student s3("s3",66);
student s4("s4",11);
student s5("s5",44);
set<student,FunStudent> set1;
set1.insert(s1);
set1.insert(s2);
set1.insert(s3);
set1.insert(s4);
set1.insert(s5);
//迭代器遍历
for(set<student,FuncStudent>::iterator it=set1.begin();it!=set1.end();++it)
{
cout<<it->name<<it->age<<endl;
}
}
4.set的大小
1.set.size(); //返回容器中元素的数目
2.set.empty();//判断容器是否为空
5.set的删除
1.set.clear(); //清除所有元素
2.set.erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
3.set.erase(beg,end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
4.set.erase(elem); //删除容器中值为elem的元素。
set集合的添加、遍历、删除基本操作
注意的点:集合 元素唯一 自动排序 不能按照[]插入数据
set<int> set1;
for(int i=0;i<5;i++)
{
int tmp=rand();
set1.insert(tmp);
}
//插入 证明 元素的唯一性 在set集合里面
//输出结果41 100 6334 18467 19169 26500 证明了元素的唯一性
set1.insert(100);
set1.insert(100);
set1.insert(100);
//遍历
for(set<int>::iterator it=set1.begin();it!=set1.end();++it)
{
cout<<*it<<" ";
}
//输出结果41 100 6334 18467 19169 26500
//开始删除
while (!set1.empty())
{
//先找到头部元素
set<int>::iterator it = set1.begin();
cout << *it << " ";
//从头部开始删
set1.erase(set1.begin());
}
}
6.set的查找
- set.find(elem); //查找elem元素,返回指向elem元素的迭代器
- set.count(elem);//返回容器中值为elem的元素个数。对set来说,要么是0,要么是1.对multiset来说,值可能大于1
- set.lower_bound(elem);//返回一个大于栋宇elem元素的迭代器
- set.upper_bound(elem);//返回第一个大于elem元素的迭代器
- set.equal_range(elem);//返回容器中与elem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如【beg,end);
set<int> set1;
for(int i=0;i<10;i++)
{
set1.insert(i+1);
}
find用法
set<int>::iterator it0 =set1.find(5);
cout<<"it0:"<<*it0<<endl;//返回的是5这个元素的第一个迭代器位置 结果it0:5
count用法
int num1=set1.count(5);
cout<<"num1:"<<num1<<endl; //查找set容器中关于5的元素有几个 结果num1:1
lower_bound()用法
set<int>::iterator it1=set1.lower_bound(5);
//大于等于5的元素的迭代器位置
cout<<"it1:"<<*it1<<endl; //结果输出为 it1:5
upper_bound()用法
set<int>::iterator it2=set1.upper_bound(5);
cout<<"it2:"<<*it2<<endl; //返回大于5元素的迭代器位置 结果:it2:6
出现pair对组的情况下使用
pair<set<int>::iterator,set<int>::iterator> pairIt=set1.equal_range(5);
set<int>::iterator it1=pairIt.first;
set<int>::iterator it2=pairIt.second;
cout<<"it1:"<<*it1<<"it2:"<<*it2<<endl;
结果为 it1:5 it2:6
7、multiset 与set区别
1、set支持唯一键值,每个元素只能出现一次,而multiset中同一值可以出现多次
2、multiset也可以自动排序
int main()
{
int tmp=0;
multiset<int> set1;
printf("请往multiset容器中插入值:");
scanf("%d",&tmp);
while(tmp!=0)
{
set1.insewrt(tmp);
printf("请往multiset容器中插入值:");
scanf("%d",&tmp);
}
//遍历
for(multiset<int>::iterator it=set1.begin();it!=set1.end();++it)
{
cout<<*it<<"";
}
while(!set1.empty())
{
multiset<int>::iterator it2=set1.begin();
cout<< *it2<<end;
set1.erase(it2);
}
return 0;
}