zoukankan      html  css  js  c++  java
  • STL源代码分析——STL算法merge合并算法

    前言

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

    源代码中介绍了函数mergeinplace_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 << '
    ';
    
    	  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 << '
    ';
    
    	  return 0;
    	}
    	Output:
    	The resulting vector contains: 5 10 10 15 20 20 25 30 40 50
    */

    參考资料:

    《STL源代码分析》侯杰

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

  • 相关阅读:
    信息系统开发内容
    系统开发项目环境
    操作系统学习基础
    进程管理、内存管理、存储管理初步了解
    操作系统导论
    Hadoop学习2
    Hadoop学习
    LiveScript 字面量
    初识LiveScript
    在使用Cocos2d-JS 开发过程中需要用到的单体设计模式
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4827875.html
Copyright © 2011-2022 走看看