注意事项
- 四种相关算法:并集、交集、差集、对称差集
- 本章的四个算法要求元素不可以重复并且经过了排序
- 底层接受STL的set/multiset容器作为输入空间
- 不接受底层为hash_set和hash_multiset两种容器
并集 set_union
- s1 U s2
- 考虑到s1 和 s2中每个元素都不唯一,如果单个元素在S1中出现了m次,在s2中出现了n次,那么该数值在并集区间内出现的次数是 max(n,m),假设m小于n。那么m个数来自s1,m-n个数来自s2
- 稳定算法 相对次序不会改变
- 版本一使用 operator <
- 版本二使用 comp 进行比较
- 注意:set已经排好顺序
template <class InputIterator1,class InputIterator2,class OutputIterator>
OutputIterator set_union(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,OutputIterator result){//如果均没有到达末尾//在两个区间内分别移动迭代器,首先将元素较小的数值(假设为A区)记录于目标区,移动A区迭代器使其前进,同一时间B区迭代器保持不变//如果两个迭代器指向的元素的大小是一致的,均移动两个迭代器while(true){//只要两个区间中有一个到达末尾就需要结束循环//将尚未到达尾端的区间的所有剩余元素拷贝到目的端//此刻的[first1,last1)和[first2,last2)之中有一个是空白的区间if (first1==last1)return std::copy(first2,last2,result);if (first2==last2)return std::copy(first1,last1,result);if (*first1 < *first2){*result = *first1;++first1;} else if(*first1 > *first2){*result = *first2;++first2;} else{ //*first1 == *first2*result = *first1;++first1;++first2;}++result;}}
int main(){int first[] = {5,10,15,20,25};int second[] = {50,40,30,20,10};std::vector<int>v(10);std::vector<int>::iterator it;std::sort(first,first+5); //5,10,15,20,25std::sort(second,second+5); //10,20,30,40,50it = std::set_union(first,first+5,second,second+5,v.begin()); // 5 10 15 20 25 30 40 50 0 0v.resize(it-v.begin()); // 5 10 15 20 25 30 40 50std::cout << "The union has " << (v.size()) << " elements:\n";for (auto tmp : v) {std::cout << tmp << " ";}std::cout << std::endl;
}///Users/chy/Desktop/exceptional/cmake-build-debug/exceptional
//The union has 8 elements:
//5 10 15 20 25 30 40 50
//
//Process finished with exit code 0
交集 set_intersection
- 构造元素的交集,即同时出现在两个集合中的元素
- 返回迭代器指向输出区间的尾端
- 考虑到s1 和 s2中每个元素都不唯一,如果单个元素在S1中出现了m次,在s2中出现了n次,那么该数值在交集区间内出现的次数是 min(n,m)
- 稳定算法 相对次序不会改变
- 版本一使用 operator <
- 版本二使用 comp 进行比较
- 注意:set已经排好顺序
template <class InputIterator1,class InputIterator2,class OutputIterator>
OutputIterator set_intersection(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,OutputIterator result){while(first1!=last1 && first2!=last2){if (*first1 < *first2)++first1;else if (*first1 > *first2){++first2;} else{*result = *first1;++first1;++first2;++result;}}return result;
}
int main(){int first[] = {5,10,15,20,25};int second[] = {50,40,30,20,10};std::vector<int>v(10);std::vector<int>::iterator it;std::sort(first,first+5); //5,10,15,20,25std::sort(second,second+5); //10,20,30,40,50it = std::set_intersection(first,first+5,second,second+5,v.begin()); // 10 20 0 0 0 0 0 0 0 0v.resize(it-v.begin()); // 10 20std::cout << "The intersection has " << (v.size()) << " elements:\n";for (auto tmp : v) {std::cout << tmp << " ";}std::cout << std::endl;
}///Users/chy/Desktop/exceptional/cmake-build-debug/exceptional
//The union has 2 elements:
//10 20
//
//Process finished with exit code 0
差集 set_difference
- 构造集合S1 - S2。此集合包含出现于S1但是不出现于S2的每一个元素
- 返回迭代器指向输出区间的尾端
- 考虑到s1 和 s2中每个元素都不唯一,如果单个元素在S1中出现了m次,在s2中出现了n次,那么该数值在交集区间内出现的次数是 max(m-n,0)
- 稳定算法 相对次序不会改变
- 版本一使用 operator <
- 版本二使用 comp 进行比较
- 注意:set已经排好顺序
template <class InputIterator1,class InputIterator2,class OutputIterator>
OutputIterator set_difference(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,OutputIterator result){while(first1!=last1 && first2!=last2){if (*first1 < *first2){*result = *first1;++result;++first1;}else if (*first1 > *first2){++first2;} else{++first1;++first2;}}return std::copy(first1,last1,result);
}
int main(){int first[] = {5,10,15,20,25};int second[] = {50,40,30,20,10};std::vector<int>v(10);std::vector<int>::iterator it;std::sort(first,first+5); //5,10,15,20,25std::sort(second,second+5); //10,20,30,40,50it = std::set_difference(first,first+5,second,second+5,v.begin()); // 5 15 25 0 0 0 0 0 0 0v.resize(it-v.begin()); // 5 15 25std::cout << "The difference has " << (v.size()) << " elements:\n";for (auto tmp : v) {std::cout << tmp << " ";}std::cout << std::endl;
}///Users/chy/Desktop/exceptional/cmake-build-debug/exceptional
//The union has 2 elements:
//5 15 25
//
//Process finished with exit code 0
对称差集 set_symmetric_difference
- 构造出 (s1 - s2) U (s2 - s1)
- 打印出现于s1但是不出现于s2 以及出现于s2但是不出现于s1的每一个元素
- 考虑到s1 和 s2中每个元素都不唯一,如果单个元素在S1中出现了m次,在s2中出现了n次,那么该数值在交集区间内出现的次数是 | n - m|
- 稳定算法 相对次序不会改变
- 版本一使用 operator <
- 版本二使用 comp 进行比较
- 注意:set已经排好顺序
template <class InputIterator1,class InputIterator2,class OutputIterator>
OutputIterator set_symmetric_difference(InputIterator1 first1,InputIterator1 last1,InputIterator2 first2,InputIterator2 last2,OutputIterator result){while (true){//以下两个条件不会同时成立 即if (first1 == last1){return std::copy(first2,last2,result);}if (first2 == last2){return std::copy(first1,last1,result);}if (*first1 < *first2){*result = *first1;++result;++first1;}else if (*first1 > *first2){*result = *first2;++result;++first2;} else{++first1;++first2;}}
}
int main(){int first[] = {5,10,15,20,25};int second[] = {50,40,30,20,10};std::vector<int>v(10);std::vector<int>::iterator it;std::sort(first,first+5); //5,10,15,20,25std::sort(second,second+5); //10,20,30,40,50it = std::set_symmetric_difference(first,first+5,second,second+5,v.begin()); //5 15 25 30 40 50 0 0 0 0v.resize(it-v.begin()); // 5 15 25 30 40 50std::cout << "The set_symmetric_difference has " << (v.size()) << " elements:\n";for (auto tmp : v) {std::cout << tmp << " ";}std::cout << std::endl;
}///Users/chy/Desktop/exceptional/cmake-build-debug/exceptional
//The union has 2 elements:
//5 15 25 30 40 50
//
//Process finished with exit code 0