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
