前言

因为在前文的《STL算法剖析》中。源代码剖析许多。不方便学习。也不方便以后复习,这里把这些算法进行归类。对他们单独的源代码剖析进行解说。本文介绍的STL算法中的merge合并算法。

源代码中介绍了函数merge、inplace_merge。并对这些函数的源代码进行具体的剖析,并适当给出使用样例,具体详见以下源代码剖析。

merge合并算法源代码剖析

// merge, with and without an explicitly supplied comparison function.
//将两个已排序的区间[first1,last1)和区间[first2,last2)合并
/*
函数功能:Combines the elements in the sorted ranges [first1,last1) and [first2,last2),
into a new range beginning at result with all its elements sorted. 函数原型:
default (1) :版本号一
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result);
custom (2) :版本号二
template <class InputIterator1, class InputIterator2,
class OutputIterator, class Compare>
OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
InputIterator2 first2, InputIterator2 last2,
OutputIterator result, Compare comp);
*/
//版本号一:
template <class _InputIter1, class _InputIter2, class _OutputIter>
_OutputIter merge(_InputIter1 __first1, _InputIter1 __last1,
_InputIter2 __first2, _InputIter2 __last2,
_OutputIter __result) {
__STL_REQUIRES(_InputIter1, _InputIterator);
__STL_REQUIRES(_InputIter2, _InputIterator);
__STL_REQUIRES(_OutputIter, _OutputIterator);
__STL_REQUIRES_SAME_TYPE(
typename iterator_traits<_InputIter1>::value_type,
typename iterator_traits<_InputIter2>::value_type);
__STL_REQUIRES(typename iterator_traits<_InputIter1>::value_type,
_LessThanComparable);
//两个序列都尚未到达尾端。则运行while循环
/*
情况1:若序列二元素较小,则记录到目标区。且移动序列二的迭代器,可是序列一的迭代器不变.
情况2:若序列一元素较小或相等,则记录到目标区,且移动序列一的迭代器,可是序列二的迭代器不变.
最后:把剩余元素的序列拷贝到目标区
*/
while (__first1 != __last1 && __first2 != __last2) {
//情况1
if (*__first2 < *__first1) {//若序列二元素较小
*__result = *__first2;//将元素记录到目标区
++__first2;//移动迭代器
}
//情况2
else {//若序列一元素较小或相等
*__result = *__first1;//将元素记录到目标区
++__first1;//移动迭代器
}
++__result;//更新目标区位置,以便下次记录数据
}
//若有序列到达尾端,则把没到达尾端的序列剩余元素拷贝到目标区
//此时,区间[first1,last1)和区间[first2,last2)至少一个必然为空
return copy(__first2, __last2, copy(__first1, __last1, __result));
}
//版本号二
template <class _InputIter1, class _InputIter2, class _OutputIter,
class _Compare>
_OutputIter merge(_InputIter1 __first1, _InputIter1 __last1,
_InputIter2 __first2, _InputIter2 __last2,
_OutputIter __result, _Compare __comp) {
__STL_REQUIRES(_InputIter1, _InputIterator);
__STL_REQUIRES(_InputIter2, _InputIterator);
__STL_REQUIRES_SAME_TYPE(
typename iterator_traits<_InputIter1>::value_type,
typename iterator_traits<_InputIter2>::value_type);
__STL_REQUIRES(_OutputIter, _OutputIterator);
__STL_BINARY_FUNCTION_CHECK(_Compare, bool,
typename iterator_traits<_InputIter1>::value_type,
typename iterator_traits<_InputIter1>::value_type);
while (__first1 != __last1 && __first2 != __last2) {
if (__comp(*__first2, *__first1)) {
*__result = *__first2;
++__first2;
}
else {
*__result = *__first1;
++__first1;
}
++__result;
}
return copy(__first2, __last2, copy(__first1, __last1, __result));
}
//merge函数举例:
/*
#include <iostream> // std::cout
#include <algorithm> // std::merge, std::sort
#include <vector> // std::vector int main () {
int first[] = {5,10,15,20,25};
int second[] = {50,40,30,20,10};
std::vector<int> v(10); std::sort (first,first+5);
std::sort (second,second+5);
std::merge (first,first+5,second,second+5,v.begin()); std::cout << "The resulting vector contains:";
for (std::vector<int>::iterator it=v.begin(); it!=v.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n'; return 0;
}
Output:
The resulting vector contains: 5 10 10 15 20 20 25 30 40 50
*/ // inplace_merge and its auxiliary functions.
//版本号一的辅助函数,无缓冲区的操作
template <class _BidirectionalIter, class _Distance>
void __merge_without_buffer(_BidirectionalIter __first,
_BidirectionalIter __middle,
_BidirectionalIter __last,
_Distance __len1, _Distance __len2) {
if (__len1 == 0 || __len2 == 0)
return;
if (__len1 + __len2 == 2) {
if (*__middle < *__first)
iter_swap(__first, __middle);
return;
}
_BidirectionalIter __first_cut = __first;
_BidirectionalIter __second_cut = __middle;
_Distance __len11 = 0;
_Distance __len22 = 0;
if (__len1 > __len2) {
__len11 = __len1 / 2;
advance(__first_cut, __len11);
__second_cut = lower_bound(__middle, __last, *__first_cut);
distance(__middle, __second_cut, __len22);
}
else {
__len22 = __len2 / 2;
advance(__second_cut, __len22);
__first_cut = upper_bound(__first, __middle, *__second_cut);
distance(__first, __first_cut, __len11);
}
_BidirectionalIter __new_middle
= rotate(__first_cut, __middle, __second_cut);
__merge_without_buffer(__first, __first_cut, __new_middle,
__len11, __len22);
__merge_without_buffer(__new_middle, __second_cut, __last, __len1 - __len11,
__len2 - __len22);
} template <class _BidirectionalIter, class _Distance, class _Compare>
void __merge_without_buffer(_BidirectionalIter __first,
_BidirectionalIter __middle,
_BidirectionalIter __last,
_Distance __len1, _Distance __len2,
_Compare __comp) {
if (__len1 == 0 || __len2 == 0)
return;
if (__len1 + __len2 == 2) {
if (__comp(*__middle, *__first))
iter_swap(__first, __middle);
return;
}
_BidirectionalIter __first_cut = __first;
_BidirectionalIter __second_cut = __middle;
_Distance __len11 = 0;
_Distance __len22 = 0;
if (__len1 > __len2) {
__len11 = __len1 / 2;
advance(__first_cut, __len11);
__second_cut = lower_bound(__middle, __last, *__first_cut, __comp);
distance(__middle, __second_cut, __len22);
}
else {
__len22 = __len2 / 2;
advance(__second_cut, __len22);
__first_cut = upper_bound(__first, __middle, *__second_cut, __comp);
distance(__first, __first_cut, __len11);
}
_BidirectionalIter __new_middle
= rotate(__first_cut, __middle, __second_cut);
__merge_without_buffer(__first, __first_cut, __new_middle, __len11, __len22,
__comp);
__merge_without_buffer(__new_middle, __second_cut, __last, __len1 - __len11,
__len2 - __len22, __comp);
}
//版本号一的辅助函数,有缓冲区的操作
template <class _BidirectionalIter1, class _BidirectionalIter2,
class _Distance>
_BidirectionalIter1 __rotate_adaptive(_BidirectionalIter1 __first,
_BidirectionalIter1 __middle,
_BidirectionalIter1 __last,
_Distance __len1, _Distance __len2,
_BidirectionalIter2 __buffer,
_Distance __buffer_size) {
_BidirectionalIter2 __buffer_end;
if (__len1 > __len2 && __len2 <= __buffer_size) {//缓冲区足够放置序列二
__buffer_end = copy(__middle, __last, __buffer);
copy_backward(__first, __middle, __last);
return copy(__buffer, __buffer_end, __first);
}
else if (__len1 <= __buffer_size) {//缓冲区足够放置序列一
__buffer_end = copy(__first, __middle, __buffer);
copy(__middle, __last, __first);
return copy_backward(__buffer, __buffer_end, __last);
}
else//若缓冲区仍然不够,则调用STL算法rotate,不使用缓冲区
return rotate(__first, __middle, __last);
} template <class _BidirectionalIter1, class _BidirectionalIter2,
class _BidirectionalIter3>
_BidirectionalIter3 __merge_backward(_BidirectionalIter1 __first1,
_BidirectionalIter1 __last1,
_BidirectionalIter2 __first2,
_BidirectionalIter2 __last2,
_BidirectionalIter3 __result) {
if (__first1 == __last1)
return copy_backward(__first2, __last2, __result);
if (__first2 == __last2)
return copy_backward(__first1, __last1, __result);
--__last1;
--__last2;
while (true) {
if (*__last2 < *__last1) {
*--__result = *__last1;
if (__first1 == __last1)
return copy_backward(__first2, ++__last2, __result);
--__last1;
}
else {
*--__result = *__last2;
if (__first2 == __last2)
return copy_backward(__first1, ++__last1, __result);
--__last2;
}
}
} template <class _BidirectionalIter1, class _BidirectionalIter2,
class _BidirectionalIter3, class _Compare>
_BidirectionalIter3 __merge_backward(_BidirectionalIter1 __first1,
_BidirectionalIter1 __last1,
_BidirectionalIter2 __first2,
_BidirectionalIter2 __last2,
_BidirectionalIter3 __result,
_Compare __comp) {
if (__first1 == __last1)
return copy_backward(__first2, __last2, __result);
if (__first2 == __last2)
return copy_backward(__first1, __last1, __result);
--__last1;
--__last2;
while (true) {
if (__comp(*__last2, *__last1)) {
*--__result = *__last1;
if (__first1 == __last1)
return copy_backward(__first2, ++__last2, __result);
--__last1;
}
else {
*--__result = *__last2;
if (__first2 == __last2)
return copy_backward(__first1, ++__last1, __result);
--__last2;
}
}
}
//版本号一的辅助函数,有缓冲区的操作
template <class _BidirectionalIter, class _Distance, class _Pointer>
void __merge_adaptive(_BidirectionalIter __first,
_BidirectionalIter __middle,
_BidirectionalIter __last,
_Distance __len1, _Distance __len2,
_Pointer __buffer, _Distance __buffer_size) {
if (__len1 <= __len2 && __len1 <= __buffer_size) {
//case1:把序列一放在缓冲区
_Pointer __buffer_end = copy(__first, __middle, __buffer);
//直接调用归并函数merge
merge(__buffer, __buffer_end, __middle, __last, __first);
}
else if (__len2 <= __buffer_size) {
//case2:把序列二放在缓冲区
_Pointer __buffer_end = copy(__middle, __last, __buffer);
__merge_backward(__first, __middle, __buffer, __buffer_end, __last);
}
else {//case3:缓冲区不足放置不论什么一个序列
_BidirectionalIter __first_cut = __first;
_BidirectionalIter __second_cut = __middle;
_Distance __len11 = 0;
_Distance __len22 = 0;
if (__len1 > __len2) {//若序列一比較长
__len11 = __len1 / 2;//计算序列一的一半
advance(__first_cut, __len11);//让first_cut指向序列一的中间位置
//找出*__first_cut在[middle,last)区间中的第一个不小于*__first_cut的元素位置
__second_cut = lower_bound(__middle, __last, *__first_cut);
//计算middle到__second_cut之间的距离。保存在__len22
distance(__middle, __second_cut, __len22);
}
else {//若序列二比較长
__len22 = __len2 / 2;//计算序列二的一半
advance(__second_cut, __len22);//让__second_cut指向序列二的中间位置
//找出*__second_cut在[first,middle)区间中的第一个大于*__second_cut的元素位置
__first_cut = upper_bound(__first, __middle, *__second_cut);
//计算__first到__first_cut之间的距离,保存在__len11
distance(__first, __first_cut, __len11);
}
_BidirectionalIter __new_middle =
__rotate_adaptive(__first_cut, __middle, __second_cut, __len1 - __len11,
__len22, __buffer, __buffer_size);
//对左半段递归调用
__merge_adaptive(__first, __first_cut, __new_middle, __len11,
__len22, __buffer, __buffer_size);
//对右半段递归调用
__merge_adaptive(__new_middle, __second_cut, __last, __len1 - __len11,
__len2 - __len22, __buffer, __buffer_size);
}
} template <class _BidirectionalIter, class _Distance, class _Pointer,
class _Compare>
void __merge_adaptive(_BidirectionalIter __first,
_BidirectionalIter __middle,
_BidirectionalIter __last,
_Distance __len1, _Distance __len2,
_Pointer __buffer, _Distance __buffer_size,
_Compare __comp) {
if (__len1 <= __len2 && __len1 <= __buffer_size) {
_Pointer __buffer_end = copy(__first, __middle, __buffer);
merge(__buffer, __buffer_end, __middle, __last, __first, __comp);
}
else if (__len2 <= __buffer_size) {
_Pointer __buffer_end = copy(__middle, __last, __buffer);
__merge_backward(__first, __middle, __buffer, __buffer_end, __last,
__comp);
}
else {
_BidirectionalIter __first_cut = __first;
_BidirectionalIter __second_cut = __middle;
_Distance __len11 = 0;
_Distance __len22 = 0;
if (__len1 > __len2) {
__len11 = __len1 / 2;
advance(__first_cut, __len11);
__second_cut = lower_bound(__middle, __last, *__first_cut, __comp);
distance(__middle, __second_cut, __len22);
}
else {
__len22 = __len2 / 2;
advance(__second_cut, __len22);
__first_cut = upper_bound(__first, __middle, *__second_cut, __comp);
distance(__first, __first_cut, __len11);
}
_BidirectionalIter __new_middle =
__rotate_adaptive(__first_cut, __middle, __second_cut, __len1 - __len11,
__len22, __buffer, __buffer_size);
__merge_adaptive(__first, __first_cut, __new_middle, __len11,
__len22, __buffer, __buffer_size, __comp);
__merge_adaptive(__new_middle, __second_cut, __last, __len1 - __len11,
__len2 - __len22, __buffer, __buffer_size, __comp);
}
}
//版本号一的辅助函数
template <class _BidirectionalIter, class _Tp, class _Distance>
inline void __inplace_merge_aux(_BidirectionalIter __first,
_BidirectionalIter __middle,
_BidirectionalIter __last, _Tp*, _Distance*) {
_Distance __len1 = 0;
distance(__first, __middle, __len1);//计算序列一的长度
_Distance __len2 = 0;
distance(__middle, __last, __len2);//计算序列二的长度 //使用临时缓冲区
_Temporary_buffer<_BidirectionalIter, _Tp> __buf(__first, __last);
if (__buf.begin() == 0)//若缓冲区配置失败
//则调用不使用缓冲区的合并操作
__merge_without_buffer(__first, __middle, __last, __len1, __len2);
else//若分配成功
//则调用具有缓冲区的合并操作
__merge_adaptive(__first, __middle, __last, __len1, __len2,
__buf.begin(), _Distance(__buf.size()));
} template <class _BidirectionalIter, class _Tp,
class _Distance, class _Compare>
inline void __inplace_merge_aux(_BidirectionalIter __first,
_BidirectionalIter __middle,
_BidirectionalIter __last, _Tp*, _Distance*,
_Compare __comp) {
_Distance __len1 = 0;
distance(__first, __middle, __len1);
_Distance __len2 = 0;
distance(__middle, __last, __len2); _Temporary_buffer<_BidirectionalIter, _Tp> __buf(__first, __last);
if (__buf.begin() == 0)
__merge_without_buffer(__first, __middle, __last, __len1, __len2, __comp);
else
__merge_adaptive(__first, __middle, __last, __len1, __len2,
__buf.begin(), _Distance(__buf.size()),
__comp);
}
//将两个已排序的序列[first,middle)和[middle,last)合并成单一有序序列.
//若原来是增序,如今也是递增排序,若原来是递减排序,如今也是递减排序
/*
函数功能:Merges two consecutive sorted ranges: [first,middle) and [middle,last),
putting the result into the combined sorted range [first,last).
函数原型:
default (1) :版本号一
template <class BidirectionalIterator>
void inplace_merge (BidirectionalIterator first, BidirectionalIterator middle,
BidirectionalIterator last);
custom (2) :版本号二
template <class BidirectionalIterator, class Compare>
void inplace_merge (BidirectionalIterator first, BidirectionalIterator middle,
BidirectionalIterator last, Compare comp);
*/
//版本号一
template <class _BidirectionalIter>
inline void inplace_merge(_BidirectionalIter __first,
_BidirectionalIter __middle,
_BidirectionalIter __last) {
__STL_REQUIRES(_BidirectionalIter, _Mutable_BidirectionalIterator);
__STL_REQUIRES(typename iterator_traits<_BidirectionalIter>::value_type,
_LessThanComparable);
if (__first == __middle || __middle == __last)//若有空序列,则之间返回
return;
__inplace_merge_aux(__first, __middle, __last,
__VALUE_TYPE(__first), __DISTANCE_TYPE(__first));
}
//版本号二
template <class _BidirectionalIter, class _Compare>
inline void inplace_merge(_BidirectionalIter __first,
_BidirectionalIter __middle,
_BidirectionalIter __last, _Compare __comp) {
__STL_REQUIRES(_BidirectionalIter, _Mutable_BidirectionalIterator);
__STL_BINARY_FUNCTION_CHECK(_Compare, bool,
typename iterator_traits<_BidirectionalIter>::value_type,
typename iterator_traits<_BidirectionalIter>::value_type);
if (__first == __middle || __middle == __last)
return;
__inplace_merge_aux(__first, __middle, __last,
__VALUE_TYPE(__first), __DISTANCE_TYPE(__first),
__comp);
}
//inplace_merge函数举例:
/*
#include <iostream> // std::cout
#include <algorithm> // std::inplace_merge, std::sort, std::copy
#include <vector> // std::vector 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);
std::sort (second,second+5); it=std::copy (first, first+5, v.begin());
std::copy (second,second+5,it); std::inplace_merge (v.begin(),v.begin()+5,v.end()); std::cout << "The resulting vector contains:";
for (it=v.begin(); it!=v.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n'; return 0;
}
Output:
The resulting vector contains: 5 10 10 15 20 20 25 30 40 50
*/

參考资料:

《STL源代码分析》侯杰

版权声明:本文博主原创文章,博客,未经同意不得转载。

STL源代码分析——STL算法merge合并算法的更多相关文章

  1. STL源代码分析——STL算法sort排序算法

    前言 因为在前文的<STL算法剖析>中,源代码剖析许多,不方便学习,也不方便以后复习.这里把这些算法进行归类,对他们单独的源代码剖析进行解说.本文介绍的STL算法中的sort排序算法,SG ...

  2. STL源代码分析——STL算法remove删除算法

    前言 因为在前文的<STL算法剖析>中,源代码剖析许多.不方便学习,也不方便以后复习,这里把这些算法进行归类.对他们单独的源代码剖析进行解说.本文介绍的STL算法中的remove删除算法. ...

  3. STL源代码剖析——STL算法stl_algo.h

    前言 在前面的博文中剖析了STL的数值算法.基本算法和set集合算法.本文剖析STL其它的算法,比如排序算法.合并算法.查找算法等等.在剖析的时候.会针对函数给出一些样例说明函数的使用.源代码出自SG ...

  4. STL源代码剖析——STL算法之set集合算法

    前言 本节介绍set集合的相关算法,各自是并集set_union,差集set_difference,交集set_intersection 和对称差集set_symmetric_difference.这 ...

  5. STL源代码分析--萃取编程(traits)技术的实现

    1.为什么要出现? 依照默认认定.一个模板给出了一个单一的定义,能够用于用户能够想到的不论什么模板參数!可是对于写模板的人而言,这样的方式并不灵活.特别是遇到模板參数为指针时,若想实现与类型的參量不一 ...

  6. STL 源代码分析 算法 stl_algo.h -- merge

    本文senlie原版的,转载请保留此地址:http://blog.csdn.net/zhengsenlie merge (应用于有序区间) ------------------------------ ...

  7. STL 源代码分析 算法 stl_heap.h

    本文senlie原版的.转载请保留此地址:http://blog.csdn.net/zhengsenlie heap ----------------------------------------- ...

  8. STL 源代码分析 算法 stl_algo.h -- includes

    本文senlie原,转载请保留此地址:http://blog.csdn.net/zhengsenlie includes(应用于有序区间) ------------------------------ ...

  9. STL 源代码分析 算法 stl_algo.h -- binary_search

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie binary_search -------------------------------- ...

随机推荐

  1. poj 1789 Truck History(kruskal算法)

    主题链接:http://poj.org/problem?id=1789 思维:一个一个点,每两行之间不懂得字符个数就看做是权值.然后用kruskal算法计算出最小生成树 我写了两个代码一个是用优先队列 ...

  2. Eclipse4.4.2手动安装Veloeclipse-2.0.8

    引言:     新安装了Eclipse最新版本 4.4.2 Luna(月神),由于项目中使用到了模板引擎Velocity,所以想安装一个Velocity插件, 在网上找了一下,看到Google的vel ...

  3. java 对map排序

    public static Map<String, String> sortMapByKey(Map<String, String> map) { if (map == nul ...

  4. VB6.0“挑衅”.NET!

    来到与两年前接触VB,现在学习VB.NET,这两个看起来真的不得不说,这是相对的似(ps:一分之差,只有三个字母),计等.但他们有又什么不同呢?都说VB.NET高级,比VB究竟高级在哪里了?是不是VB ...

  5. 重新想象 Windows 8 Store Apps (11) - 控件之 ListView 和 GridView

    原文:重新想象 Windows 8 Store Apps (11) - 控件之 ListView 和 GridView [源码下载] 重新想象 Windows 8 Store Apps (11) - ...

  6. 水声通信(传声)于iOS、Android在情景-depth分析(包括一些声通信源)

    最近的水声通信非常热,特别是,非常嵌入式设备备受瞩目使用,前段时间公布了声通信部分源代码(iOS和Android版本号.下载源的最新版本:点击打开链接 http://download.csdn.net ...

  7. WF系列——工作流基本知识

    工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档.信息或任务的过程自动进行,从而实现某个预期的业务目标 ...

  8. C# WinForm多线程(三)Control.Invoke

    下面我们就把在Windows Form软件中使用Invoke时的多线程要注意的问题给大家做一个介绍. 首先,什么样的操作需要考虑使用多线程?总的一条就是,负责与用户交互的线程(以下简称为UI线程)应该 ...

  9. 我已提取并尝试使用启动脚本(./start navicat)来启动 Navicat Linux 版本号,但没有反应

    具体的安装教程,參考这个navicat_for_mysql_10.0.11在linux下的安装,介绍的非常具体 參考这个 :我可否在 64-bit Linux 执行 Navicat? 推荐navica ...

  10. PHP情人:p十几天来学习hp第一天

    我这里是暂时的 Apache web server 和 MY SQL 如WEB,在php-4.3.3下的环境做的程序.当然要简单的构建和訪问查看数据库 PHPMYADMIN 不可少.  以下简介一下P ...