前言:
set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的数据结构,在插入元素时,它会自动调整二叉树的排列,把该元素放到合适的位置,以确保每个字数根节点的键值大于左子树所有节点的键值,而小于右子树所有节点的键值;另外,还要确保根节点左子树的高度于右子树的高度相等,这样,二叉树的高度最小,从而检索速度最快。要注意的是,它不会重复插入相同键值的元素,而采取忽略处理。
平衡二叉检索树的检索使用中序遍历算法,检索效率高于vector,deque,list等容器。另外,采用中序遍历算法可将键值由小到大遍历出来,所以,可以理解为平衡二叉检索树在插入元素时,就会自动将元素按键值由小到大的顺序排列。
对于set容器的键值,不可直接取修改。因为如果把容器中的一个键值修改了,set容器会根据新的键值旋转子树,以保持平衡,这样,修改的键值很可能就不在原来的那个位置上了。换句话说,构造set集合的主要目的就是为了快速检索。
multiset(多重集合容器),map(映照容器)和multimap(多重映照容器)的内部结构也是平衡二叉检索树。
在用set容器前,需要在程序的头文件中包含声明“#include<set>”。
1.创建set集合对象
创建set对象时,需要制定元素的类型,这一点和其他的容器不一样。
#include<set>
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
set<int>s;
return 0;
}
2.元素的插入和中序遍历
采用insert()方法把元素插入集合中去,插入的具体规则在默认的比较规则下,是按照元素值由小到大进行排列。如果自己制定了比较规则函数,则按照自定义比较函数插入。
使用前向迭代器对集合中序遍历,其结果正好是元素排序的结果。
#include<set>
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
set<int>s;
s.insert(8);
s.insert(1);
s.insert(12);
s.insert(6);
s.insert(8);
set<int>::iterator it;
for(it=s.begin(); it!=s.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
return 0;
}
输出:
3.元素的反向遍历
使用反向迭代器reverse_iterator可以反向遍历集合,输出的结果正好是几何元素的翻向排序结果。它需要用到rbegin()和rend()两个方法,它们分别给出了反向便利的开始位置和结束位置。
#include<set>
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
set<int>s;
s.insert(8);
s.insert(1);
s.insert(12);
s.insert(6);
s.insert(8);
set<int>::reverse_iterator rit;
for(rit=s.rbegin(); rit!=s.rend(); rit++)
{
cout<<*rit<<" ";
}
cout<<endl;
return 0;
}
输出:
4.元素的删除
clear()可清空容器,与插入元素的处理一样,集合具有高效的删除处理功能,并自动重新调整内部的红黑树的平衡。删除的对象可以是某个迭代器位置上的元素,等于某键值的元素,一个区间上的元素和清空集合。
#include<set>
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
set<int>s;
s.insert(8);
s.insert(1);
s.insert(12);
s.insert(6);
s.insert(8);
set<int>::reverse_iterator rit;
for(rit=s.rbegin(); rit!=s.rend(); rit++)
{
cout<<*rit<<" ";
}
cout<<endl;
s.clear();
cout<<s.size()<<endl;
return 0;
}
输出:
5.元素的检索
使用find()方法对集合进行搜索,如果找到了搜查的键值,则返回该键值的迭代器位置,否则,返回ji和最后一个元素houm后面的一个位置,即end();
#include<set>
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
set<int>s;
s.insert(8);
s.insert(1);
s.insert(12);
s.insert(6);
s.insert(8);
set<int>::iterator it;
it=s.find(6);
if(it!=s.end())
cout<<*it<<endl;
else
cout<<"not find it"<<endl;
it=s.find(20);
if(it!=s.end())
cout<<*it<<endl;
else
cout<<"not find it"<<endl;
return 0;
}
输出:
6.自定义比较函数
使用insert()将元素插入到集合中去的时候,集合会根据设定的比较函数将钙元素放到该放的节点上去。在定义集合的时候,如果没有指定比较函数,那么采用默认的比较函数,即按照键值由小到大的顺序插入元素。在很多情况下,需要自己编写比较函数。
编写比较函数有两种方法。
1.如果元素不是结构体,那么,可以编写比较函数。下面的这个程序编写的比较规则要求按照键值由大到小的顺序将元素插入到集合中:
#include<set>
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct myComp
{
bool operator()(const int &a,const int &b)
{
return a>b;
}
};
int main()
{
set<int,myComp>s;
s.insert(8);
s.insert(1);
s.insert(12);
s.insert(6);
s.insert(8);
set<int,myComp>::iterator it;
for(it=s.begin(); it!=s.end(); it++)
{
cout<<*it<<" ";
}
cout<<endl;
return 0;
}
输出:
2.如果元素是结构体,那么,可以直接把比较函数写在结构体内:
#include<set>
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
string name;
float score;
bool operator<(const node &a)const
{
return a.score<score;
}
};
int main()
{
set<node>s;
node a;
a.name="Jack";
a.score=80.5;
s.insert(a);
a.name="Tomi";
a.score=20.5;
s.insert(a);
a.name="Nacy";
a.score=60.5;
s.insert(a);
set<node>::iterator it;
for(it=s.begin(); it!=s.end(); it++)
{
cout<<(*it).name<<" "<<(*it).score<<endl;
}
return 0;
}
输出: