容器用于存储数据,在STL中,set是一个类似数学中”集合”的容器,可以进行交集并集的计算,且容器中不允许出现重复元素,set在日常使用中经常见到,值得注意的是,set内部使用二叉树存储数据,运算速度很快。
参考手册:http://www.cplusplus.com/reference/set/set/
set的声明如下,
template < class T, // set::key_type/value_type class Compare = less<T>, // set::key_compare/value_compare class Alloc = allocator<T> // set::allocator_type > class set;
第一个参数T是容器类型,第二个和第三个参数都提供的默认值,其中第二个参数是 比较器,用于给容器中元素进行大小排序,默认为less<T>,也可以自己指定,第三个参数是分配器,该参数指定使用哪个分配器对象管理内存,如果省略该模板参数的值,则容器模板将默认使用allocator<T>,这个类使用new和delete
set容器的常用方法:
初始化:
set容器常用的初始化方法为:
默认初始化
使用区间初始化
使用复制构造函数初始化
#include <iostream> #include <string> #include <set> #include <cmath> struct Point { double x, y; }; struct PointCmp { bool operator()(const Point& lhs, const Point& rhs) const { return std::hypot(lhs.x, lhs.y) < std::hypot(rhs.x, rhs.y); } }; int main() { // (1) 默认初始化器!!常用 std::set<std::string> a; a.insert("cat"); a.insert("dog"); a.insert("horse"); for(auto& str: a) std::cout << str << ' '; std::cout << '\n'; // (2) 迭代器初始化器!!常用//使用区间进行初始化,也可以用数组的区间进行初始化。 std::set<std::string> b(a.find("dog"), a.end()); for(auto& str: b) std::cout << str << ' '; std::cout << '\n'; // (3) 复制构造函数 std::set<std::string> c(a); c.insert("another horse"); for(auto& str: c) std::cout << str << ' '; std::cout << '\n'; // (4) 移动构造函数 std::set<std::string> d(std::move(a)); for(auto& str: d) std::cout << str << ' '; std::cout << '\n'; std::cout << "moved-from set is "; for(auto& str: a) std::cout << str << ' '; std::cout << '\n'; // (5) initializer_list 构造函数 std::set<std::string> e {"one", "two", "three", "five", "eight"}; for(auto& str: e) std::cout << str << ' '; std::cout << '\n'; // 自定义比较器 std::set<Point, PointCmp> z = {{2, 5}, {3, 4}, {1, 1}}; z.insert({1, -1}); // 这会失败,因为 1,-1 的长度等于 1,1 for(auto& p: z) std::cout << '(' << p.x << ',' << p.y << ") "; std::cout << '\n'; } //输出: cat dog horse dog horse another horse cat dog horse cat dog horse moved-from set is eight five one three two (1,1) (3,4) (2,5)
insert():插入元素
常用insert(A,B)//A,B分别是两个迭代器,或两个数组中的指针,把[A,B)区间的元素插入容器。
insert(E)//直接插入一个元素
erase():删除操作:
iterator erase (const_iterator position);//删除迭代器指向位置的元素 size_type erase (const value_type& val);//删除这个元素 iterator erase (const_iterator first, const_iterator last);//删除这个区间的元素
find():查找元素
如果找到了,则返回指向这个元素的迭代器,如果没有找到,则返回一个指向最后一个元素尾部的迭代器. (end()的返回值,这个迭代器指向最后一个元素的下一个元素,所以无效)
// set::find #include <iostream> #include <set> int main () { std::set<int> myset; std::set<int>::iterator it; // set some initial values: for (int i=1; i<=5; i++) myset.insert(i*10); // set: 10 20 30 40 50 it=myset.find(20); myset.erase (it); myset.erase (myset.find(40)); std::cout << "myset contains:"; for (it=myset.begin(); it!=myset.end(); ++it) std::cout << ' ' << *it; std::cout << '\n'; return 0; }
begin()//返回一个指向元素开头的迭代器(ps:关于迭代器,我们可以把它当作指针)
end()//返回一个指向最后一个元素尾部的迭代器
// set::begin/end #include <iostream> #include <set> int main () { int myints[] = {75,23,65,42,13}; std::set<int> myset (myints,myints+5);//使用数组初始化set容器中的元素 std::cout << "myset contains:"; for (std::set<int>::iterator it=myset.begin(); it!=myset.end(); ++it) std::cout << ' ' << *it; std::cout << '\n'; return 0; } //输出:myset contains: 13 23 42 65 75
rbegin()/rend():返回反向迭代器
// set::rbegin/rend #include <iostream> #include <set> int main () { int myints[] = {21,64,17,78,49}; std::set<int> myset (myints,myints+5); std::set<int>::reverse_iterator rit; std::cout << "myset contains:"; for (rit=myset.rbegin(); rit != myset.rend(); ++rit) std::cout << ' ' << *rit; std::cout << '\n'; return 0; } //输出:myset contains: 78 64 49 21 17 //参数中默认的比较器是从小到大排列的,所以这里反向输出的容器元素的值
cbegin()/cend():返回一个const的迭代器
crbegin()/crend():返回const的反向迭代器
empty()//测试容器是否为空,为空则返回true.
size()//返回容器有多少元素.
max_size()//返回容器存储元素的最大值.
最后介绍一下set在集合意义上的操作
set_union()//求并集
set_intersection//交集
set_difference//差集
这三个函数的接口是相同的,他们都有5个参数,分别是:第一个集合的区间,第二个集合的区间,输出迭代器,这个迭代器指出要将操作的结果输出到哪里。
今天写累了,明天再写
待更新