C++集合基本操作
multiset
multiset是<set>库中一个非常有用的类型,可看成一个序列。插入删除都能够在O(logn)的时间内完成,并保证序列中的数是有序的,而且序列中可以存在重复的数。
可以用列表初始化和insert建立。
std::multiset<int> words1{ 1,2,2,3,4 }; int x; while (cin >> x)words1.insert(x); for (int i : words1)cout << i << " ";
假如输入3,输出为:1 2 2 3 3 4 。
inset还可以插入两个迭代器之间所有值。
std::multiset<int> words1{ 1,2,3,4,5,6,7}; vector<int> num = { 4,3,9,6 }; words1.insert(num.begin(),num.end());
可以根据元素的值或者迭代器位置删除元素
std::multiset<int> words1{ 1,2,2,3,4 }; words1.erase(2);
输出:1 3 4 。所有的2都被删除。
std::multiset<int> words1{ 1,2,2,3,4,5,7,7 }; auto iter1 = words1.begin(); auto iter2 = words1.end(); iter1++; iter1++; iter2--; words1.erase(iter1,iter2);
输出:1 2 7 。两个迭代器区间内(左闭右开)的值被删除
由于multiset是有序的,所以要放入自定义类型,就需要定义比较类cmp。
struct rec { int x, y; }; struct cmp { bool operator()(const rec& a, const rec& b) { return (a.x *a.y)<(b.x*b.y); } }; int main(){ multiset<rec, cmp>h; rec a, b, c, d; a = { 4,5 }; b = { 3,7 }; c = { 3,6 }; d = { 1,19 }; h = {a,b,c,d}; for (rec i :h)cout << i.x << " " << i.y << " "; }
结果会报错:
错误 C3848 具有类型“const cmp”的表达式会丢失一些 const-volatile 限定符以调用“bool cmp::operator ()(const rec &,const rec &)”
如下修改后成功编译。参考了:https://www.cnblogs.com/qrlozte/p/4437418.html
struct cmp { bool operator()(const rec& a, const rec& b) const { return (a.x *a.y)<(b.x*b.y); } };
并集
std::multiset<int> words1{ 1,2,2,3,4 }; std::multiset<int> words2{ 1,2,3,3,3 }; std::multiset<int> words3; std::set_union(std::begin(words1), std::end(words1), std::begin(words2), std::end(words2), std::inserter(words3, std::begin(words3))); for (int i : words3)cout << i << " ";
输出: 1 2 2 3 3 3 4 。输出并集中重复个数,为输入中重复个数的最大值。
交集
int iarr1[]={1,2,3,3,4,5,6,7,9}; int iarr2[]={1,4,3,9,10}; multiset<int> iset1(begin(iarr1),end(iarr1)); multiset<int> iset2(begin(iarr2),end(iarr2)); vector<int> ivec(20); auto iter=set_intersection(iset1.begin(),iset1.end(),iset2.begin(),iset2.end(),ivec.begin()); //返回输出末尾的迭代器 ivec.resize(iter-ivec.begin());//重新确定ivec大小
假如不重新确定大小,就会输出20个数。注意一开始初始化ivec时要给够足够大小,不然会out of range。
其实直接对有序数组做交集都是可以的,没必要先转化为multiset。
int iarr1[]={1,2,3,3,6,7,4,5}; int iarr2[]={1,4,3,10,9}; std::sort(begin(iarr1),end(iarr1)); std::sort(begin(iarr2),end(iarr2)); vector<int> ivec(10); auto iter=set_intersection(begin(iarr1),end(iarr1),begin(iarr2),end(iarr2),ivec.begin()); //ivec =1 3 4 ivec.resize(iter-ivec.begin());//重新确定ivec大小
子集判断。用include函数,判断前两个迭代器之间的集合是否包括后两个迭代器之间的集合。
std::multiset<int> words1{ 1,2,3,3,3,4,5,6}; std::multiset<int> words2{ 1,2,3,3,3 }; cout << std::boolalpha<< std::includes(words1.begin(),words1.end(),words2.begin(),words2.end() );//true std::multiset<int> words1{ 1,2,3,3,4,5,6}; std::multiset<int> words2{ 1,2,3,3,3 }; cout << std::boolalpha<< std::includes(words1.begin(),words1.end(),words2.begin(),words2.end() );//false