Set/Multiset 集合使用的是红黑树的平衡二叉检索树的数据结构,来组织泛化的元素数据,通常来说红黑树根节点每次只能衍生出两个子节点,左面的节点是小于根节点的数据集合,右面的节点是大于根节点的集合,通过这样的方式将数据组织成一颗看似像树一样的结构,而平衡一词的含义则是两边的子节点数量必须在小于等1的区间以内。
Set集合天生去重,所有元素都会根据元素的键值自动的排序,并且Set元素在确定后无法进行更改,换句话说Set的Iterator是一种Const_iterator,而Multiset则允许出现重复的数据,如需使用只需要将set<int>改为multiset<int>即可,Multiset操作方式与API函数与Set集合保持相同。
5.1 正反向遍历集合元素
这段C++代码使用了STL的set容器,展示了set容器的一些基本操作,包括插入元素、删除元素、判断容器是否为空以及遍历元素并按照一定规则排序。
代码首先创建了一个空的set<int>类型的变量var。然后,代码使用insert()函数向set容器中插入了三个整数,并调用PrintSet()函数遍历输出set容器的元素,并按照从大到小的顺序输出。PrintSet()函数中通过判断flag标记的不同来选择正向还是反向输出set容器的元素。
接下来,代码使用empty()函数判断set容器是否为空,并显示容器的元素个数。
最后,代码展示了erase()函数的用法,从set容器中删除了第一个元素和元素值为99的元素,并再次调用PrintSet()函数输出set容器的元素。
| #include <iostream>#include <set>
 
 using namespace std;
 
 void PrintSet(set<int>& s ,int flag)
 {
 if (flag == 1)
 {
 for (set<int>::iterator it = s.begin(); it != s.end(); it++)
 cout << (*it) << " ";
 }
 else if (flag == 0)
 {
 for (set<int>::reverse_iterator it = s.rbegin(); it != s.rend(); it++)
 cout << (*it) << " ";
 }
 }
 
 int main(int argc, char* argv[])
 {
 set<int> var { };
 
 var.insert(56);
 var.insert(67);
 var.insert(99);
 PrintSet(var,0);
 
 if (var.empty())
 cout << "None" << endl;
 else
 cout << "size: " << var.size() << endl;
 
 var.erase(var.begin());
 var.erase(99);
 PrintSet(var, 0);
 system("pause");
 return 0;
 }
 
 | 
5.2 查找集合中指定元素
这段C++代码使用了STL的set容器,展示了set容器的一些基本操作,包括查找元素、计算元素个数、寻找较大或较小的元素和查找范围。
代码首先创建了一个set<int>类型的变量var,并在其中插入了一些整数。然后,代码分别使用了find()和count()函数来查找元素90是否存在于set容器中,并统计了90出现的次数。
代码接下来展示了lower_bound()和upper_bound()函数的用法。其中lower_bound()函数返回第一个值大于或等于给定值的元素的迭代器,upper_bound()函数返回第一个值大于给定值的元素的迭代器。在本例中,代码使用lower_bound()函数和upper_bound()函数来查找set中与值4相邻的元素,并输出了它们的值。
最后,代码展示了equal_range()函数的用法。equal_range()函数返回一个pair,其中第一个迭代器指向set中第一个等于所给值的元素,第二个迭代器指向set中第一个大于所给值的元素。在本例中,代码使用equal_range()函数来查找值为4的元素在set中的范围,并输出了这个范围中的元素。
| #include <iostream>#include <set>
 
 using namespace std;
 
 int main(int argc, char* argv[])
 {
 set<int> var { 23,44,56,78,90,0,90,12,54,67,85,3,4,7};
 
 
 set<int>::iterator pos = var.find(90);
 if (pos != var.end())
 cout << "找到了: " << *pos << endl;
 
 
 int number = var.count(90);
 cout << "90是否存在: " << number << endl;
 
 
 set<int>::iterator it = var.lower_bound(4);
 if (it != var.end())
 cout << "找到了 lower_bound(4) 的值:" << *it << endl;
 
 
 set<int>::iterator it2 = var.upper_bound(4);
 if (it2 != var.end())
 cout << "找到了 upper_bound(4) 的值:" << *it2 << endl;
 
 
 
 pair<set<int>::iterator, set<int>::iterator> ret = var.equal_range(4);
 if (ret.first != var.end())
 cout << "找到 lower_bound(4): " << *(ret.first) << endl;
 if (ret.second != var.end())
 cout << "找到 upper_bound(4): " << *(ret.second) << endl;
 
 system("pause");
 return 0;
 }
 
 | 
5.3 设置默认集合排序方式
这是一个使用STL中的set容器进行数据存储和排序的示例代码,其中使用了自定义比较函数MyCompare以实现按从大到小的顺序进行排序。set 是一个有序不重复元素集合,它是通过红黑树实现的,插入、删除和查找元素的平均时间复杂度都是O(log n)。在此代码中,set容器存储了int类型的数据,并使用MyCompare作为元素的比较方式,从而实现按从大到小的顺序排序。可以看到,通过set容器和自定义比较函数,我们可以非常方便地实现数据存储和排序的功能。
| #include <iostream>#include <set>
 #include <string>
 
 using namespace std;
 
 class MyCompare
 {
 public: bool operator()(int v1, int v2) {
 return v1 > v2;
 
 }
 };
 
 int main(int argc, char* argv[])
 {
 set<int, MyCompare> var;
 
 var.insert(6);
 var.insert(3);
 var.insert(9);
 
 for (set<int, MyCompare>::iterator it = var.begin(); it != var.end(); it++)
 cout << *it << endl;
 
 system("pause");
 return 0;
 }
 
 | 
5.4 向集合插入自定义类型
这段代码演示了如何在set容器中插入自定义的Person数据类型,并且通过重载运算符实现自定义的比较规则。通过MyCompare类定义的比较方法,实现了set容器中自定义类型的降序排列。最后,通过迭代器遍历容器,输出每个Person对象的名字和年龄。
| #include <iostream>#include <set>
 #include <string>
 
 using namespace std;
 
 class Person {
 public:
 string m_name;
 int m_age;
 
 public: Person(string name, int age) {
 this->m_name = name;
 this->m_age = age;
 }
 };
 
 class MyCompare{
 
 public: bool operator()(const Person & p1, const Person & p2){
 if (p1.m_age > p2.m_age)
 return true;
 return false;
 }
 };
 
 int main(int argc, char* argv[])
 {
 set<Person,MyCompare> var;
 
 Person p1("dawa", 22);
 Person p2("xiwa", 44);
 var.insert(p1);
 var.insert(p2);
 
 
 for (set<Person, MyCompare>::iterator it = var.begin(); it != var.end();it ++)
 {
 cout << "Name: " << (*it).m_name << "Age: " << (*it).m_age << endl;
 }
 system("pause");
 return 0;
 }
 
 |