set 集合容器
set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的数据结构,在插入元素时,它会自动调整二叉树的排列,把该元素放在适当的位置,以确保每个字数根节点的键值大于左子树所有节点 的键值,而小于右子树所有节点的键值;另外,还得确保根节点左子树的高度与右子树的高度相等,这样,二叉树的高度最小,从而检索速度最快。要注意的是,它不会重复插入相同键值的元素,而采取忽略处理。如图为一个典型的红黑树。
一.元素的插入与中序遍历(用insert()方法把元素插入集合中去,插入的具体规则在默认的比较规则下,是按元素值由小到大插入,如果自己指定了比较规则函数,则按自定义比较规则函数插入)
1 #include<iostream> 2 #include<set> 3 using namespace std; 4 int main() 5 { 6 set<int> s; //定义元素类型为int的集合对象s,当前没有任何元素; 7 s.insert(8); //插入了4个元素,但由于8有重复,第二次插入的8并没有执行; 8 s.insert(6); 9 s.insert(12); 10 s.insert(8); //第二次插入8,重复元素,不会插入; 11 set<int>::iterator it; 12 for(it=s.begin();it!=s.end();it++) //中序遍历集合中的所有元素; 13 { 14 cout<<*it<<" "; 15 } 16 cout<<endl; 17 return 0; 18 }
运行结果
6 8 12
二.元素的方向遍历(使用方向迭代器reverse_iterator可以方向遍历集合,输出的结果正好是集合元素的反向排序结果。它需要用到rbegin()和rend()两个方法,它们分别给出了遍历的开始位置和结束位置)
1 #include<iostream> 2 #include<set> 3 using namespace std; 4 int main() 5 { 6 set<int> s; 7 s.insert(8); 8 s.insert(12); 9 s.insert(6); 10 s.insert(8); 11 set<int>::reverse_iterator it; 12 for(it=s.rbegin();it!=s.rend();it++) //方向遍历集合中的元素 13 { 14 cout<<*it<<" "; 15 } 16 cout<<endl; 17 return 0; 18 }
运行结果
12 8 6
三.元素的检索(使用find()方法对集合进行搜索,如果找到查找的键值,则返回该键值的迭代器位置,否则,返回集合最后一个元素后面的一个位置,即end())
1 #include<iostream> 2 #include<set> 3 using namespace std; 4 int main() 5 { 6 set<int> s; 7 s.insert(8); 8 s.insert(12); 9 s.insert(1); 10 s.insert(6); 11 set<int>::iterator it; 12 it=s.find(6); 13 if(it!=s.end()) cout<<*it<<endl; 14 else cout<<"no find it"<<endl; 15 it=s.find(20); 16 if(it!=s.end()) cout<<*it<<endl; 17 else cout<<"no find it"<<endl; 18 return 0; 19 }
运行结果
6 no find it
四.自定义比较函数
编写比较函数有两种方法:
(1)如果元素不是结构体,那么,可以编写比较函数。下面这个程序编写的比较规则是要求按键值由大到小的顺序将元素插入到集合中。
1 #include<iostream> 2 #include<set> 3 using namespace std; 4 struct myComp //自定义比较函数myComp,重载“()”操作符 5 { 6 bool operator()(const int &a,const int &b) 7 {return a>b;} 8 }; 9 int main() 10 { 11 set<int,myComp> s; //采用的比较函数是myComp 12 s.insert(8); 13 s.insert(6); 14 s.insert(12); 15 set<int,myComp>::iterator it; 16 for(it=s.begin();it!=s.end();it++) 17 { 18 cout<<*it<<" "; 19 } 20 cout<<endl; 21 return 0; 22 }
运行结果
12 8 6
(2)如果元素时结构体,那么,可以直接把比较函数写在结构体内。
1 #include<iostream> 2 #include<set> 3 #include<string> 4 using namespace std; 5 struct Info 6 { 7 string name; 8 float score; 9 bool operator<(const Info &a) const //重载“<”操作符,自定义排序规则 10 { 11 return a.score<score; //按score由大到小排列。如果要由小到大排列,使用“>”号即可 12 } 13 }; 14 int main() 15 { 16 set<Info> s; 17 Info info; //定义Info类型的元素 18 info.name="Jack"; 19 info.score=80.5; 20 s.insert(info); 21 info.name="Nacy"; 22 info.score=20.5; 23 s.insert(info); 24 info.name="Tomi"; 25 info.score=60.5; 26 s.insert(info); 27 set<Info>::iterator it; 28 for(it=s.begin();it!=s.end();it++) 29 { 30 cout<<(*it).name<<":"<<(*it).score<<endl; 31 } 32 return 0; 33 }
运行结果
Jack:80.5 Tomi:60.5 Nacy:20.5
multiset多重集合容器
multiset与set一样,也是使用红黑树来组织元素数据的,唯一不同的是,multiset允许重复的元素键值插入,而set则不允许。如图为multiset容器内部结构示意图
multiset也需声明头文件包含"#include<set>"