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有申请了额外的缓存区,所以可以直接归并到本身的容器里.可以参考这里