前言
在学习csp题解的时候接触到这个数据结构,故在此记录一下其概念及应用。
基本概念
set的底层采用的是红黑树,所有元素都会根据元素的键值自动排序,方便管理元素,但不支持直接修改键值。
应用
头文件调用
#include <iostream>
#include <set>
set的Api
insert 插入元素
@brief 试图将元素插入到%set中。
@param[in] 要插入的元素。
@return <std::set<T>::iterator, bool> <迭代器,插入是否成功标志>
erase 擦除元素
@brief 根据提供的键擦除元素。
@param[in] 要擦除的元素的键。
@return std::size_t 被擦除的元素的数量。此函数从%set中擦除按给定键定位的所有元素。注意,此函数只擦除元素,如果元素本身是指针,则不会以任何方式触及指向的内存。管理指针是用户的责任。
size 求大小
@brief 返回%set的大小。
@return std::size_t 大小
max_size 最最大大小
@brief 返回%set的最大大小。
@return std::size_t 大小
begin 获取第一个元素的指针
@brief 返回一个指向%set中第一个元素的只读(常量)迭代器。迭代是按照键的升序进行的。
@return std::set<int>::iterator 迭代器
end 获取最后一个元素的下一个位置的指针
@brief 返回一个只读(常量)迭代器,指向%set集合中最后一个元素的往下一位置。迭代是按照键的升序进行的。
@return std::set<int>::iterator 迭代器
find 寻找元素
@brief 试图定位%set中的元素。
@param[in] 要定位的元素。
@return std::set<int>::iterator 迭代器指向寻找的元素,如果未找到则指向end()。此函数接受一个键并尝试定位与该键匹配的元素。如果成功,则函数返回指向所查找元素的迭代器。如果不成功,则返回end()迭代器。
count 获取指定元素的个数
@brief 查找元素的数量。
@param[in] 被定位的元素。
@return std::size_t 具有指定键的元素数量。这个函数只对多集有意义;对于set,结果将是0(不存在)或1(存在)。
lower_bound 获取大于等于给定元素的第一个元素指针
@brief 查找匹配给定键的子序列的开头。
@param[in] 要定位的键。
@return std::set<int>::iterator 指向第一个等于或大于key或end()的元素的迭代器。此函数返回与给定键匹配的子元素序列中的第一个元素。如果不成功,则返回一个迭代器,指向第一个值大于给定key或end()的元素(如果不存在这样的元素)。
upper_bound 获取大于给定元素的第一个元素指针
@brief 查找匹配给定键的子序列的结尾
@param[in] 要定位的键。
@return std::set<int>::iterator 指向第一个大于key的元素的迭代器,或end()。
clear 擦除所有元素
@brief 擦除%set中的所有元素。注意,这个函数只擦除元素,如果元素本身是指针,则不会以任何方式触及指向的内存。管理指针是用户的责任。
empty 判断集合是否为空
@brief 如果%set为空则返回true。
@return bool
示例(int类型)
代码
#include <iostream>
#include <set>
using namespace std;
int main()
{
std::pair<std::set<int>::iterator, bool> temp;
int array[] = {1, -1, 2, 3, 3, 2, 2, 1};
set<int> set1;
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++)
{
temp = set1.insert(array[i]);
if(temp.second)
cout << *temp.first << " 插入成功" << endl;
else
cout << *temp.first << " 已经存在" << endl;
}
cout << endl;
cout << "set大小为:"<< set1.size() << endl;
cout << "set的最大大小为:" << set1.max_size() << endl;
cout << endl;
cout << "set的元素有:";
set<int>::iterator iter = set1.begin();
while (iter != set1.end())
{
cout << *iter << " ";
iter++;
}
cout << endl;
cout << endl;
set1.erase(1);
cout << "使用erase删除元素1后,set的size值为:" << set1.size() << endl;
cout << endl;
iter = set1.find(1);
if (iter == set1.end())
cout << "1 is not in set!" << endl;
else
cout << "1 is in set!" << endl;
if(set1.count(1))
cout << "1 is in set!" << endl;
else
cout << "1 is not in set!" << endl;
cout << endl;
cout << "大于等于2的元素是" << *set1.lower_bound(2) << endl;
cout << "大于2的元素是" << *set1.upper_bound(2) << endl;
cout << endl;
set1.clear();
if (set1.empty())
{
cout << "set.clear()后,set为空!" << endl;
}
cout << "set的size值为:" << set1.size() << endl;
cout << "set的maxsize的值为:" << set1.max_size() << endl;
cout << endl;
system("pause");
}
结果
示例(结构体类型)
注意
需要对 < 重定向
因为set会自动升序,需要告诉其按结构体内哪个值进行升序。
代码
#include <iostream>
#include <set>
struct Info{
int nums;
int scope;
bool operator < (const Info &x) const
{
if(scope < x.scope) return true;
if(scope == x.scope && nums < x.nums) return true;
return false;
}
};
using namespace std;
int main()
{
std::pair<std::set<Info>::iterator, bool> temp;
Info info[5] = {{99,2}, {90,1}, {95,3}, {95,3},{89,1}};
set<Info> set1;
for (int i = 0; i < sizeof(info) / sizeof(info[0]); i++)
{
temp = set1.insert(info[i]);
if(temp.second)
cout << "{" << (*temp.first).nums << ", " << (*temp.first).scope << "}" << " 插入成功" << endl;
else
cout << "{" << (*temp.first).nums << ", " << (*temp.first).scope << "}" << " 已经存在" << endl;
}
cout << endl;
cout << "set大小为:"<< set1.size() << endl;
cout << "set的最大大小为:" << set1.max_size() << endl;
cout << endl;
cout << "set的元素有:";
set<Info>::iterator iter = set1.begin();
while (iter != set1.end())
{
cout << "{" << (*iter).nums << ", " << (*iter).scope << "}" << " ";
iter++;
}
cout << endl;
cout << endl;
set1.erase(info[1]);
cout << "使用erase删除元素{90, 1}后,set的size值为:" << set1.size() << endl;
cout << endl;
iter = set1.find(info[1]);
if (iter == set1.end())
cout << "{90, 1} is not in set!" << endl;
else
cout << "{90, 1} is in set!" << endl;
if(set1.count(info[1]))
cout << "{90, 1} is in set!" << endl;
else
cout << "{90, 1} is not in set!" << endl;
cout << endl;
Info com = {99, 2};
cout << "键值大于等于{99, 2}的元素是" << "{" << (*set1.lower_bound(com)).nums << ", " << (*set1.lower_bound(com)).scope << "}" << endl;
cout << "键值大于{99, 2}的元素是" << "{" << (*set1.upper_bound(com)).nums << ", " << (*set1.upper_bound(com)).scope << "}" << endl;
com = {0, 2};
cout << "键值大于{0, 2}的元素是" << "{" << (*set1.upper_bound(com)).nums << ", " << (*set1.upper_bound(com)).scope << "}" << endl;
cout << endl;
set1.clear();
if (set1.empty())
{
cout << "set.clear()后,set为空!" << endl;
}
cout << "set的size值为:" << set1.size() << endl;
cout << "set的maxsize的值为:" << set1.max_size() << endl;
cout << endl;
system("pause");
}
结果
特别注意
重定向规则会影响查找。
比如lower_bound和upper_bound,示例代码中有例子展示。
而且重定向规则可以使升序排列变成降序排列。