【STL源码剖析读书笔记】【第6章】算法之inplace_merge算法

来源:互联网 发布:马薇薇为什么离婚 知乎 编辑:程序博客网 时间:2024/05/24 05:38

1、  inplace_merge()函数将两个连接在一起的排序序列[first, middle)和[middle, last)结合成单一序列并保持有序。inplace_merge()函数是stable操作。

2、  inplace_merge()版本一的源代码,只讨论了有暂时缓冲区的情况

template <class BidirectionalIterator>inline void inplace_merge(BidirectionalIterator first,BidirectionalIterator middle,BidirectionalIterator last) {//其中一个序列为空,什么也不做if (first == middle || middle == last) return;__inplace_merge_aux(first, middle, last, value_type(first),distance_type(first));}//辅助函数template <class BidirectionalIterator, class T, class Distance>inline void __inplace_merge_aux(BidirectionalIterator first,BidirectionalIterator middle,BidirectionalIterator last, T*, Distance*) {Distance len1 = 0;distance(first, middle, len1);Distance len2 = 0;distance(middle, last, len2);//会使用额外的内存空间temporary_buffer<BidirectionalIterator, T> 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 BidirectionalIterator, class Distance, class Pointer>void __merge_adaptive(BidirectionalIterator first,BidirectionalIterator middle,BidirectionalIterator last, Distance len1, Distance len2,Pointer buffer, Distance buffer_size) {if (len1 <= len2 && len1 <= buffer_size) {//case1:缓冲区足够安置序列一Pointer end_buffer = copy(first, middle, buffer);merge(buffer, end_buffer, middle, last, first);}else if (len2 <= buffer_size) {//case2:缓冲区足够安置序列二Pointer end_buffer = copy(middle, last, buffer);__merge_backward(first, middle, buffer, end_buffer, last);}else {//case3:缓冲区不能安置任何一个序列BidirectionalIterator first_cut = first;BidirectionalIterator 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);}//旋转操作BidirectionalIterator 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 BidirectionalIterator1, class BidirectionalIterator2,class Distance>BidirectionalIterator1 __rotate_adaptive(BidirectionalIterator1 first,BidirectionalIterator1 middle,BidirectionalIterator1 last,Distance len1, Distance len2,BidirectionalIterator2 buffer,Distance buffer_size) {<span style="white-space:pre"></span>BidirectionalIterator2 buffer_end;<span style="white-space:pre"></span>if (len1 > len2 && len2 <= buffer_size) {<span style="white-space:pre"></span>//缓冲区能安置序列二<span style="white-space:pre"></span>buffer_end = copy(middle, last, buffer);<span style="white-space:pre"></span>copy_backward(first, middle, last);<span style="white-space:pre"></span>return copy(buffer, buffer_end, first);<span style="white-space:pre"></span>}<span style="white-space:pre"></span>else if (len1 <= buffer_size) {<span style="white-space:pre"></span>//缓冲区能安置序列一<span style="white-space:pre"></span>buffer_end = copy(first, middle, buffer);<span style="white-space:pre"></span>copy(middle, last, first);<span style="white-space:pre"></span>return copy_backward(buffer, buffer_end, last);<span style="white-space:pre"></span>}<span style="white-space:pre"></span>else  {<span style="white-space:pre"></span>//缓冲区不足,调用rotate()函数<span style="white-space:pre"></span>rotate(first, middle, last);<span style="white-space:pre"></span>advance(first, len2);<span style="white-space:pre"></span>return first;<span style="white-space:pre"></span>}}

3、  图解说明

case 1:缓冲区足够安置序列一


case 2:缓冲区足够安置序列二


case 3:假设缓冲区大小为3,小于序列一的长度4和序列二的长度5,缓冲区不能安置任何一个序列


 旋转操作后:


左段递归调用:


右端递归调用:


排序完成。



0 0
原创粉丝点击