四.c++中的算法--排序及相关操作---合并排序
来源:互联网 发布:关于网络的论文 编辑:程序博客网 时间:2024/06/03 20:06
5.合并排序
1.两个已序集合的总和
- merge()
函数模板:
版本一
template<class InputIt1, class InputIt2, class OutputIt>OutputIt merge(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first){ for (; first1 != last1; ++d_first) { if (first2 == last2) {//序列为空 return std::copy(first1, last1, d_first); } if (*first2 < *first1) {//升序排列 *d_first = *first2; ++first2; } else { *d_first = *first1; ++first1; } } return std::copy(first2, last2, d_first);//将序列剩余部分拷贝到目标区间}
版本二
template<class InputIt1, class InputIt2, class OutputIt, class Compare>OutputIt merge(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Compare comp){ for (; first1 != last1; ++d_first) { if (first2 == last2) { return std::copy(first1, last1, d_first); } if (comp(*first2, *first1)) {//自定义二元比较函数 *d_first = *first2; ++first2; } else { *d_first = *first1; ++first1; } } return std::copy(first2, last2, d_first);}
说明:
1. 源容器的两个序列应该是有序的,但是无序也可以
2. 要保证目标空间够大,否则需要使用插入行迭代器。如back_inserter
3. 一般情况,目标区间和源区间不允许重复。
2.两个已序集合的并集(union)
- set_union()
用于将已序的两个集合合并,重复的元素被唯一化。
函数模板为:
template<class InputIt1, class InputIt2, class OutputIt>OutputIt set_union(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first){ for (; first1 != last1; ++d_first) { if (first2 == last2)//序列二为空 return std::copy(first1, last1, d_first); if (*first2 < *first1) {//默认比较规则,升序合并 *d_first = *first2++; } else { *d_first = *first1; if (!(*first1 < *first2))//除去相等元素 ++first2; ++first1; } } return std::copy(first2, last2, d_first);}//第二种形式template<class InputIt1, class InputIt2, class OutputIt, class Compare>OutputIt set_union(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Compare comp){ for (; first1 != last1; ++d_first) { if (first2 == last2) return std::copy(first1, last1, d_first); if (comp(*first2, *first1)) { *d_first = *first2++; } else { *d_first = *first1; if (!comp(*first1, *first2)) ++first2; ++first1; } } return std::copy(first2, last2, d_first);}
说明:
1. 其中,两个源序列需要是有序的,不然会报错
2. 同时,当源区间本来就有重复元素时,会保留这些重复元素,元素的重复个数是两个源区间中重复个数较大的那个数值。
例子:
-------------省略----------------vector<int> vec1 = { 1, 2, 4, 5, 6, 3 };vector<int> vec2 = { 1, 2, 2,2,3,3,4,4,5 };vector<int> vec4;//先排序sort(vec1.begin(),vec1.end());sort(vec2.begin(), vec2.end());//并集set_union(vec1.begin(),vec1.end(),vec2.begin(),vec2.end(),back_inserter(vec4));-------------省略----------------
结果为:
vec4: 1 2 2 2 3 3 4 4 5 6
可以发现重复元素时序列2这个重复元素多的序列个数
3.两个已序集合的交集(intersection)
- set_intersection()
- 算法用于将已序的两个区间的元素合并,新生区间内的元素应该是同时属于两个源区间的元素
- 如果源区间存在重复元素,那么新生区间也存在重复元素,并且使属于数目小的那个重复个数。
函数原型为:
template<class InputIt1, class InputIt2, class OutputIt>OutputIt set_intersection(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first){ while (first1 != last1 && first2 != last2) { if (*first1 < *first2) { ++first1; } else { if (!(*first2 < *first1)) {//寻找公有元素 *d_first++ = *first1++; } ++first2; } } return d_first;}//第二种形式template<class InputIt1, class InputIt2, class OutputIt, class Compare>OutputIt set_intersection(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Compare comp){ while (first1 != last1 && first2 != last2) { if (comp(*first1, *first2)) { ++first1; } else { if (!comp(*first2, *first1)) { *d_first++ = *first1++; } ++first2; } } return d_first;}
说明:
1. 第一种形式: 使用默认比较规则:operator<
2. 第二种形式: 使用自定义二元比较函数: comp
3. 返回值: 目标区间最后一个公有元素的后一个位置。
4. 所有元素都有序排列
例子:
--------------------------省略------------------- vector<int> vec1 = { 1, 2, 4, 5, 6, 3 }; vector<int> vec2 = { 1, 2, 2,2,3,3,4,4,5 }; vector<int> vec4; set_intersection(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), back_inserter(vec4));--------------------------省略-------------------
结果为:
vec4: 1 2 3 4 5
4.两个已序集合的差集 (difference)
set_difference()
- 算法实现两个源区间之间的求差。
- 新生区间的元素为只在序列1中存在的元素。
函数原型:
template<class InputIt1, class InputIt2, class OutputIt>OutputIt set_difference(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first){ while (first1 != last1) { if (first2 == last2) return std::copy(first1, last1, d_first); if (*first1 < *first2) {//选择序列1中独有的元素 *d_first++ = *first1++; } else { if (! (*first2 < *first1)) { ++first1; } ++first2;//跳过相同的元素 } } return d_first;}//第二种形式:template<class InputIt1, class InputIt2, class OutputIt, class Compare>OutputIt set_difference( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Compare comp){ while (first1 != last1) { if (first2 == last2) return std::copy(first1, last1, d_first); if (comp(*first1, *first2)) { *d_first++ = *first1++; } else { if (!comp(*first2, *first1)) { ++first1; } ++first2; } } return d_first;}
说明:
1. 第一种形式: 使用默认比较规则:operator<
2. 第二种形式: 使用自定义二元比较函数: comp
3. 返回值: 目标区间最后一个公有元素的后一个位置。
4. 所有元素都有序排列
5. 如果源区间有重复元素,目标区间也会有,重复的个数是区间一减去源区间二的个数。如果区间二的个数大于区间一的个数,那么重复个数为0 ,即不会存在此元素。
例子:
--------------省略--------------------- vector<int> vec1 = { 1, 2,4, 5, 6, 3,3 }; vector<int> vec2 = { 1, 2,2,3,4,4,5 }; vector<int> vec4; sort(vec1.begin(),vec1.end()); sort(vec2.begin(), vec2.end()); set_difference(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), back_inserter(vec4));--------------省略--------------------
结果为:
vec4: 3 6
set_symmetric_difference
函数原型;
版本一template<class InputIt1, class InputIt2, class OutputIt>OutputIt set_difference(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first){ while (first1 != last1) { //序列2为空,返回序列1 if (first2 == last2) return std::copy(first1, last1, d_first); if (*first1 < *first2) {//返回序列1和序列2中小的元素 *d_first++ = *first1++; } else { if (*first2 < *first1) { *d_first++ = *first2; } else { ++first1; } ++first2;//两个元素相等,跳过 } } return std::copy(first2, last2, d_first);//返回序列2剩下的部分}//第二种形式:template<class InputIt1, class InputIt2, class OutputIt, class Compare>OutputIt set_difference(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Compare comp){ while (first1 != last1) { if (first2 == last2) return std::copy(first1, last1, d_first); if (comp(*first1, *first2)) { *d_first++ = *first1++; } else { if (comp(*first2, *first1)) { *d_first++ = *first2; } else { ++first1; } ++first2; } } return std::copy(first2, last2, d_first);}
例子:
-----------------省略------------- vector<int> vec1 = {1,3,5,7,9}; vector<int> vec2 = {0,2,3,3,4,6,8 }; vector<int> vec4; set_symmetric_difference(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), back_inserter(vec4));-----------------省略-------------
结果为:
vec4: 0 1 2 3 4 5 6 7 8 9
可以看错,这个函数是选择两个序列的有序序列,如果两个序列有重复元素,元素的个数为多个减去少个的个数,如3的个数为2-1 =1。
【相关文档】
1.C++集合操作之集合对称并集:std::set_symmetric_difference
5.连贯的已序区间合并算法
- inplace_merge()
inplace_merge函数的作用和merge函数差不多,只不过是在一个容器中进行归并。将[first,mid) 和 [mid,last)这两个区间进行归并成一个有序序列。
函
数原型:
template< class BidirIt >void inplace_merge( BidirIt first, BidirIt middle, BidirIt last );template< class BidirIt, class Compare>void inplace_merge( BidirIt first, BidirIt middle, BidirIt last, Compare comp );
说明:
1. 第一个形式:operator<的第一个版本使用比较的元素,
2. 第二个版本使用给定的比较函数comp.
3. [first,middle)和[middle,last)这两个区间必须都是升序或者降序。
例子:
------------省略------------- vector<int> vec2 = {1,3,5,7,2,4,5,8 }; inplace_merge(vec2.begin(), vec2.begin() + 4, vec2.end());------------省略-------------
结果为:
vec2: 1 2 3 4 5 5 7 8
- 四.c++中的算法--排序及相关操作---合并排序
- 四.c++中的算法--排序及相关操作---局部排序
- 四.c++中的算法--排序及相关操作---堆操作
- 四.c++中的算法--排序及相关操作---搜索
- 四.c++中的算法--排序及相关操作---全部元素排序
- 四.c++中的算法--排序及相关操作---根据某个元素排序
- c++STL排序及相关操作
- 合并排序算法 C代码
- 漫谈经典排序算法:四、归并排序(合并排序)
- 漫谈经典排序算法:四、归并排序(合并排序)
- 漫谈经典排序算法:四、归并排序(合并排序)
- 漫谈经典排序算法:四、归并排序(合并排序)
- DataTable相关:DataTable排序、查询、合并操作
- DataTable相关:DataTable排序、查询、合并操作
- 排序算法---合并排序
- 排序算法-合并排序
- 10.排序及相关操作
- 算法导论,合并排序,c实现。
- 四.c++中的算法--排序及相关操作---堆操作
- Python 面向对象(进阶篇)
- Socket编程之htons(), ntohl(), ntohs(),htons() 函数
- 1.DeckBulid 基本代码笔记
- 不用管这个QwQ
- 四.c++中的算法--排序及相关操作---合并排序
- eclipse classpath路径
- 四.c++中的算法--排序及相关操作---搜索
- 初始化二维vector的方法
- 训练总结 8.15
- Oracle分页工具类+分页对象JavaBean
- Python爬虫——实战一:爬取京东产品价格(逆向工程方法)
- image图片布局存在空隙的解决办法
- [分块]BZOJ 4216——Pig