C++ merge 和 inplace_merge 的区别

首先这两个包含在 algorithm 头文件里面,

要求需要归并的内容必须是有序的,
merge:从两个的有序列(两个有序列可以在同一容器内)归并第三个容器.
inplace_merge:一个容器内分两个有序的部分归并到本身的容器.

根据上面图片所说的,
merge 至多做 两段有序列长度之和 - 1 次对比,
inplace_merge在额外内存足够的情况下,恰好做 N - 1 次对比(N其实就是两段有序列长度之和 ),否则(没有足够内存用来缓存)复杂度就是 N*log(N),即若尝试分配缓存失败就会用比较低效的算法来执行.

总结

假设M,N分别为两段有序列的长度.

merge时间复杂度为O(min(M,N)),空间复杂度O(M+N).

inplace_merge,在分配缓存成功时,时间复杂度O(M+N),空间复杂度看分配的缓存,即可能为O(M),O(N)或O(M+N),否则,时间复杂度为O(N*log(N)),空间复杂度为O(1).


merge

函数定义如下:

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);

可以看出是由两个容器归并到第三个容器里,第三个容器不可以是前两个容器任何一个.

vector<int> vec1 = { 5,10,15,20,25 };
    vector<int> vec2 = { 0,10,10,25,30 };
    vector<int> vec3(vec1.size()+vec2.size());

    //vec1,vec2归并到vec3,如下
    merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec3.begin());
    //vec3:{0,5,10,10,10,15,20,25,25,30}

    //两个容器可以指向同一个容器,如下
    vector<int> vec4 = { 5,10,15,20,25 ,0,10,10,25,30 };
    merge(vec4.begin(), vec4.begin() + 5, vec4.begin() + 5, vec4.end(), vec3.begin());
    //vec3:{0,5,10,10,10,15,20,25,25,30}

    //但指向同一个容器并不严谨,重叠时并不会报错,如下
    merge(vec1.begin(), vec1.end(), vec1.begin(), vec1.end(), vec3.begin());
    //vec3:{ 5,5,10,10,15,15,20,20,25,25 }




    //但第三个容器不可以是前两个容器任何一个,因为前两个正在读取,不能直接写入
    merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec1.begin());//错误的

inplace_merge

函数定义如下:

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);

可以看出,归并的两个部分分别是first到middle,和middle到last.

vector<int> vec1 = { 5,10,15,20,25 ,0,10,10,25,30 };

    inplace_merge(vec1.begin(), vec1.begin() + 5, vec1.end());
    //vec1:{0,5,10,10,10,15,20,25,25,30}

实际上inplace_merge有申请了额外的缓存区,所以可以直接归并到本身的容器里.可以参考这里