STL源码剖析——STL算法之merge合并算法

末蓝、 2022-08-12 19:29 432阅读 0赞

前言

由于在前文的《STL算法剖析》中,源码剖析非常多,不方便学习,也不方便以后复习,这里把这些算法进行归类,对他们单独的源码剖析进行讲解。本文介绍的STL算法中的merge合并算法。源码中介绍了函数merge、inplace_merge。并对这些函数的源码进行详细的剖析,并适当给出使用例子,具体详见下面源码剖析。

merge合并算法源码剖析

  1. // merge, with and without an explicitly supplied comparison function.
  2. //将两个已排序的区间[first1,last1)和区间[first2,last2)合并
  3. /*
  4. 函数功能:Combines the elements in the sorted ranges [first1,last1) and [first2,last2),
  5. into a new range beginning at result with all its elements sorted.
  6. 函数原型:
  7. default (1) :版本一
  8. template <class InputIterator1, class InputIterator2, class OutputIterator>
  9. OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
  10. InputIterator2 first2, InputIterator2 last2,
  11. OutputIterator result);
  12. custom (2) :版本二
  13. template <class InputIterator1, class InputIterator2,
  14. class OutputIterator, class Compare>
  15. OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
  16. InputIterator2 first2, InputIterator2 last2,
  17. OutputIterator result, Compare comp);
  18. */
  19. //版本一:
  20. template <class _InputIter1, class _InputIter2, class _OutputIter>
  21. _OutputIter merge(_InputIter1 __first1, _InputIter1 __last1,
  22. _InputIter2 __first2, _InputIter2 __last2,
  23. _OutputIter __result) {
  24. __STL_REQUIRES(_InputIter1, _InputIterator);
  25. __STL_REQUIRES(_InputIter2, _InputIterator);
  26. __STL_REQUIRES(_OutputIter, _OutputIterator);
  27. __STL_REQUIRES_SAME_TYPE(
  28. typename iterator_traits<_InputIter1>::value_type,
  29. typename iterator_traits<_InputIter2>::value_type);
  30. __STL_REQUIRES(typename iterator_traits<_InputIter1>::value_type,
  31. _LessThanComparable);
  32. //两个序列都尚未到达尾端,则执行while循环
  33. /*
  34. 情况1:若序列二元素较小,则记录到目标区,且移动序列二的迭代器,但是序列一的迭代器不变.
  35. 情况2:若序列一元素较小或相等,则记录到目标区,且移动序列一的迭代器,但是序列二的迭代器不变.
  36. 最后:把剩余元素的序列复制到目标区
  37. */
  38. while (__first1 != __last1 && __first2 != __last2) {
  39. //情况1
  40. if (*__first2 < *__first1) {//若序列二元素较小
  41. *__result = *__first2;//将元素记录到目标区
  42. ++__first2;//移动迭代器
  43. }
  44. //情况2
  45. else {//若序列一元素较小或相等
  46. *__result = *__first1;//将元素记录到目标区
  47. ++__first1;//移动迭代器
  48. }
  49. ++__result;//更新目标区位置,以便下次记录数据
  50. }
  51. //若有序列到达尾端,则把没到达尾端的序列剩余元素复制到目标区
  52. //此时,区间[first1,last1)和区间[first2,last2)至少一个必定为空
  53. return copy(__first2, __last2, copy(__first1, __last1, __result));
  54. }
  55. //版本二
  56. template <class _InputIter1, class _InputIter2, class _OutputIter,
  57. class _Compare>
  58. _OutputIter merge(_InputIter1 __first1, _InputIter1 __last1,
  59. _InputIter2 __first2, _InputIter2 __last2,
  60. _OutputIter __result, _Compare __comp) {
  61. __STL_REQUIRES(_InputIter1, _InputIterator);
  62. __STL_REQUIRES(_InputIter2, _InputIterator);
  63. __STL_REQUIRES_SAME_TYPE(
  64. typename iterator_traits<_InputIter1>::value_type,
  65. typename iterator_traits<_InputIter2>::value_type);
  66. __STL_REQUIRES(_OutputIter, _OutputIterator);
  67. __STL_BINARY_FUNCTION_CHECK(_Compare, bool,
  68. typename iterator_traits<_InputIter1>::value_type,
  69. typename iterator_traits<_InputIter1>::value_type);
  70. while (__first1 != __last1 && __first2 != __last2) {
  71. if (__comp(*__first2, *__first1)) {
  72. *__result = *__first2;
  73. ++__first2;
  74. }
  75. else {
  76. *__result = *__first1;
  77. ++__first1;
  78. }
  79. ++__result;
  80. }
  81. return copy(__first2, __last2, copy(__first1, __last1, __result));
  82. }
  83. //merge函数举例:
  84. /*
  85. #include <iostream> // std::cout
  86. #include <algorithm> // std::merge, std::sort
  87. #include <vector> // std::vector
  88. int main () {
  89. int first[] = {5,10,15,20,25};
  90. int second[] = {50,40,30,20,10};
  91. std::vector<int> v(10);
  92. std::sort (first,first+5);
  93. std::sort (second,second+5);
  94. std::merge (first,first+5,second,second+5,v.begin());
  95. std::cout << "The resulting vector contains:";
  96. for (std::vector<int>::iterator it=v.begin(); it!=v.end(); ++it)
  97. std::cout << ' ' << *it;
  98. std::cout << '\n';
  99. return 0;
  100. }
  101. Output:
  102. The resulting vector contains: 5 10 10 15 20 20 25 30 40 50
  103. */
  104. // inplace_merge and its auxiliary functions.
  105. //版本一的辅助函数,无缓冲区的操作
  106. template <class _BidirectionalIter, class _Distance>
  107. void __merge_without_buffer(_BidirectionalIter __first,
  108. _BidirectionalIter __middle,
  109. _BidirectionalIter __last,
  110. _Distance __len1, _Distance __len2) {
  111. if (__len1 == 0 || __len2 == 0)
  112. return;
  113. if (__len1 + __len2 == 2) {
  114. if (*__middle < *__first)
  115. iter_swap(__first, __middle);
  116. return;
  117. }
  118. _BidirectionalIter __first_cut = __first;
  119. _BidirectionalIter __second_cut = __middle;
  120. _Distance __len11 = 0;
  121. _Distance __len22 = 0;
  122. if (__len1 > __len2) {
  123. __len11 = __len1 / 2;
  124. advance(__first_cut, __len11);
  125. __second_cut = lower_bound(__middle, __last, *__first_cut);
  126. distance(__middle, __second_cut, __len22);
  127. }
  128. else {
  129. __len22 = __len2 / 2;
  130. advance(__second_cut, __len22);
  131. __first_cut = upper_bound(__first, __middle, *__second_cut);
  132. distance(__first, __first_cut, __len11);
  133. }
  134. _BidirectionalIter __new_middle
  135. = rotate(__first_cut, __middle, __second_cut);
  136. __merge_without_buffer(__first, __first_cut, __new_middle,
  137. __len11, __len22);
  138. __merge_without_buffer(__new_middle, __second_cut, __last, __len1 - __len11,
  139. __len2 - __len22);
  140. }
  141. template <class _BidirectionalIter, class _Distance, class _Compare>
  142. void __merge_without_buffer(_BidirectionalIter __first,
  143. _BidirectionalIter __middle,
  144. _BidirectionalIter __last,
  145. _Distance __len1, _Distance __len2,
  146. _Compare __comp) {
  147. if (__len1 == 0 || __len2 == 0)
  148. return;
  149. if (__len1 + __len2 == 2) {
  150. if (__comp(*__middle, *__first))
  151. iter_swap(__first, __middle);
  152. return;
  153. }
  154. _BidirectionalIter __first_cut = __first;
  155. _BidirectionalIter __second_cut = __middle;
  156. _Distance __len11 = 0;
  157. _Distance __len22 = 0;
  158. if (__len1 > __len2) {
  159. __len11 = __len1 / 2;
  160. advance(__first_cut, __len11);
  161. __second_cut = lower_bound(__middle, __last, *__first_cut, __comp);
  162. distance(__middle, __second_cut, __len22);
  163. }
  164. else {
  165. __len22 = __len2 / 2;
  166. advance(__second_cut, __len22);
  167. __first_cut = upper_bound(__first, __middle, *__second_cut, __comp);
  168. distance(__first, __first_cut, __len11);
  169. }
  170. _BidirectionalIter __new_middle
  171. = rotate(__first_cut, __middle, __second_cut);
  172. __merge_without_buffer(__first, __first_cut, __new_middle, __len11, __len22,
  173. __comp);
  174. __merge_without_buffer(__new_middle, __second_cut, __last, __len1 - __len11,
  175. __len2 - __len22, __comp);
  176. }
  177. //版本一的辅助函数,有缓冲区的操作
  178. template <class _BidirectionalIter1, class _BidirectionalIter2,
  179. class _Distance>
  180. _BidirectionalIter1 __rotate_adaptive(_BidirectionalIter1 __first,
  181. _BidirectionalIter1 __middle,
  182. _BidirectionalIter1 __last,
  183. _Distance __len1, _Distance __len2,
  184. _BidirectionalIter2 __buffer,
  185. _Distance __buffer_size) {
  186. _BidirectionalIter2 __buffer_end;
  187. if (__len1 > __len2 && __len2 <= __buffer_size) {//缓冲区足够放置序列二
  188. __buffer_end = copy(__middle, __last, __buffer);
  189. copy_backward(__first, __middle, __last);
  190. return copy(__buffer, __buffer_end, __first);
  191. }
  192. else if (__len1 <= __buffer_size) {//缓冲区足够放置序列一
  193. __buffer_end = copy(__first, __middle, __buffer);
  194. copy(__middle, __last, __first);
  195. return copy_backward(__buffer, __buffer_end, __last);
  196. }
  197. else//若缓冲区仍然不够,则调用STL算法rotate,不使用缓冲区
  198. return rotate(__first, __middle, __last);
  199. }
  200. template <class _BidirectionalIter1, class _BidirectionalIter2,
  201. class _BidirectionalIter3>
  202. _BidirectionalIter3 __merge_backward(_BidirectionalIter1 __first1,
  203. _BidirectionalIter1 __last1,
  204. _BidirectionalIter2 __first2,
  205. _BidirectionalIter2 __last2,
  206. _BidirectionalIter3 __result) {
  207. if (__first1 == __last1)
  208. return copy_backward(__first2, __last2, __result);
  209. if (__first2 == __last2)
  210. return copy_backward(__first1, __last1, __result);
  211. --__last1;
  212. --__last2;
  213. while (true) {
  214. if (*__last2 < *__last1) {
  215. *--__result = *__last1;
  216. if (__first1 == __last1)
  217. return copy_backward(__first2, ++__last2, __result);
  218. --__last1;
  219. }
  220. else {
  221. *--__result = *__last2;
  222. if (__first2 == __last2)
  223. return copy_backward(__first1, ++__last1, __result);
  224. --__last2;
  225. }
  226. }
  227. }
  228. template <class _BidirectionalIter1, class _BidirectionalIter2,
  229. class _BidirectionalIter3, class _Compare>
  230. _BidirectionalIter3 __merge_backward(_BidirectionalIter1 __first1,
  231. _BidirectionalIter1 __last1,
  232. _BidirectionalIter2 __first2,
  233. _BidirectionalIter2 __last2,
  234. _BidirectionalIter3 __result,
  235. _Compare __comp) {
  236. if (__first1 == __last1)
  237. return copy_backward(__first2, __last2, __result);
  238. if (__first2 == __last2)
  239. return copy_backward(__first1, __last1, __result);
  240. --__last1;
  241. --__last2;
  242. while (true) {
  243. if (__comp(*__last2, *__last1)) {
  244. *--__result = *__last1;
  245. if (__first1 == __last1)
  246. return copy_backward(__first2, ++__last2, __result);
  247. --__last1;
  248. }
  249. else {
  250. *--__result = *__last2;
  251. if (__first2 == __last2)
  252. return copy_backward(__first1, ++__last1, __result);
  253. --__last2;
  254. }
  255. }
  256. }
  257. //版本一的辅助函数,有缓冲区的操作
  258. template <class _BidirectionalIter, class _Distance, class _Pointer>
  259. void __merge_adaptive(_BidirectionalIter __first,
  260. _BidirectionalIter __middle,
  261. _BidirectionalIter __last,
  262. _Distance __len1, _Distance __len2,
  263. _Pointer __buffer, _Distance __buffer_size) {
  264. if (__len1 <= __len2 && __len1 <= __buffer_size) {
  265. //case1:把序列一放在缓冲区
  266. _Pointer __buffer_end = copy(__first, __middle, __buffer);
  267. //直接调用归并函数merge
  268. merge(__buffer, __buffer_end, __middle, __last, __first);
  269. }
  270. else if (__len2 <= __buffer_size) {
  271. //case2:把序列二放在缓冲区
  272. _Pointer __buffer_end = copy(__middle, __last, __buffer);
  273. __merge_backward(__first, __middle, __buffer, __buffer_end, __last);
  274. }
  275. else {//case3:缓冲区不足放置任何一个序列
  276. _BidirectionalIter __first_cut = __first;
  277. _BidirectionalIter __second_cut = __middle;
  278. _Distance __len11 = 0;
  279. _Distance __len22 = 0;
  280. if (__len1 > __len2) {//若序列一比较长
  281. __len11 = __len1 / 2;//计算序列一的一半
  282. advance(__first_cut, __len11);//让first_cut指向序列一的中间位置
  283. //找出*__first_cut在[middle,last)区间中的第一个不小于*__first_cut的元素位置
  284. __second_cut = lower_bound(__middle, __last, *__first_cut);
  285. //计算middle到__second_cut之间的距离,保存在__len22
  286. distance(__middle, __second_cut, __len22);
  287. }
  288. else {//若序列二比较长
  289. __len22 = __len2 / 2;//计算序列二的一半
  290. advance(__second_cut, __len22);//让__second_cut指向序列二的中间位置
  291. //找出*__second_cut在[first,middle)区间中的第一个大于*__second_cut的元素位置
  292. __first_cut = upper_bound(__first, __middle, *__second_cut);
  293. //计算__first到__first_cut之间的距离,保存在__len11
  294. distance(__first, __first_cut, __len11);
  295. }
  296. _BidirectionalIter __new_middle =
  297. __rotate_adaptive(__first_cut, __middle, __second_cut, __len1 - __len11,
  298. __len22, __buffer, __buffer_size);
  299. //对左半段递归调用
  300. __merge_adaptive(__first, __first_cut, __new_middle, __len11,
  301. __len22, __buffer, __buffer_size);
  302. //对右半段递归调用
  303. __merge_adaptive(__new_middle, __second_cut, __last, __len1 - __len11,
  304. __len2 - __len22, __buffer, __buffer_size);
  305. }
  306. }
  307. template <class _BidirectionalIter, class _Distance, class _Pointer,
  308. class _Compare>
  309. void __merge_adaptive(_BidirectionalIter __first,
  310. _BidirectionalIter __middle,
  311. _BidirectionalIter __last,
  312. _Distance __len1, _Distance __len2,
  313. _Pointer __buffer, _Distance __buffer_size,
  314. _Compare __comp) {
  315. if (__len1 <= __len2 && __len1 <= __buffer_size) {
  316. _Pointer __buffer_end = copy(__first, __middle, __buffer);
  317. merge(__buffer, __buffer_end, __middle, __last, __first, __comp);
  318. }
  319. else if (__len2 <= __buffer_size) {
  320. _Pointer __buffer_end = copy(__middle, __last, __buffer);
  321. __merge_backward(__first, __middle, __buffer, __buffer_end, __last,
  322. __comp);
  323. }
  324. else {
  325. _BidirectionalIter __first_cut = __first;
  326. _BidirectionalIter __second_cut = __middle;
  327. _Distance __len11 = 0;
  328. _Distance __len22 = 0;
  329. if (__len1 > __len2) {
  330. __len11 = __len1 / 2;
  331. advance(__first_cut, __len11);
  332. __second_cut = lower_bound(__middle, __last, *__first_cut, __comp);
  333. distance(__middle, __second_cut, __len22);
  334. }
  335. else {
  336. __len22 = __len2 / 2;
  337. advance(__second_cut, __len22);
  338. __first_cut = upper_bound(__first, __middle, *__second_cut, __comp);
  339. distance(__first, __first_cut, __len11);
  340. }
  341. _BidirectionalIter __new_middle =
  342. __rotate_adaptive(__first_cut, __middle, __second_cut, __len1 - __len11,
  343. __len22, __buffer, __buffer_size);
  344. __merge_adaptive(__first, __first_cut, __new_middle, __len11,
  345. __len22, __buffer, __buffer_size, __comp);
  346. __merge_adaptive(__new_middle, __second_cut, __last, __len1 - __len11,
  347. __len2 - __len22, __buffer, __buffer_size, __comp);
  348. }
  349. }
  350. //版本一的辅助函数
  351. template <class _BidirectionalIter, class _Tp, class _Distance>
  352. inline void __inplace_merge_aux(_BidirectionalIter __first,
  353. _BidirectionalIter __middle,
  354. _BidirectionalIter __last, _Tp*, _Distance*) {
  355. _Distance __len1 = 0;
  356. distance(__first, __middle, __len1);//计算序列一的长度
  357. _Distance __len2 = 0;
  358. distance(__middle, __last, __len2);//计算序列二的长度
  359. //使用暂时缓冲区
  360. _Temporary_buffer<_BidirectionalIter, _Tp> __buf(__first, __last);
  361. if (__buf.begin() == 0)//若缓冲区配置失败
  362. //则调用不使用缓冲区的合并操作
  363. __merge_without_buffer(__first, __middle, __last, __len1, __len2);
  364. else//若分配成功
  365. //则调用具有缓冲区的合并操作
  366. __merge_adaptive(__first, __middle, __last, __len1, __len2,
  367. __buf.begin(), _Distance(__buf.size()));
  368. }
  369. template <class _BidirectionalIter, class _Tp,
  370. class _Distance, class _Compare>
  371. inline void __inplace_merge_aux(_BidirectionalIter __first,
  372. _BidirectionalIter __middle,
  373. _BidirectionalIter __last, _Tp*, _Distance*,
  374. _Compare __comp) {
  375. _Distance __len1 = 0;
  376. distance(__first, __middle, __len1);
  377. _Distance __len2 = 0;
  378. distance(__middle, __last, __len2);
  379. _Temporary_buffer<_BidirectionalIter, _Tp> __buf(__first, __last);
  380. if (__buf.begin() == 0)
  381. __merge_without_buffer(__first, __middle, __last, __len1, __len2, __comp);
  382. else
  383. __merge_adaptive(__first, __middle, __last, __len1, __len2,
  384. __buf.begin(), _Distance(__buf.size()),
  385. __comp);
  386. }
  387. //将两个已排序的序列[first,middle)和[middle,last)合并成单一有序序列.
  388. //若原来是增序,现在也是递增排序,若原来是递减排序,现在也是递减排序
  389. /*
  390. 函数功能:Merges two consecutive sorted ranges: [first,middle) and [middle,last),
  391. putting the result into the combined sorted range [first,last).
  392. 函数原型:
  393. default (1) :版本一
  394. template <class BidirectionalIterator>
  395. void inplace_merge (BidirectionalIterator first, BidirectionalIterator middle,
  396. BidirectionalIterator last);
  397. custom (2) :版本二
  398. template <class BidirectionalIterator, class Compare>
  399. void inplace_merge (BidirectionalIterator first, BidirectionalIterator middle,
  400. BidirectionalIterator last, Compare comp);
  401. */
  402. //版本一
  403. template <class _BidirectionalIter>
  404. inline void inplace_merge(_BidirectionalIter __first,
  405. _BidirectionalIter __middle,
  406. _BidirectionalIter __last) {
  407. __STL_REQUIRES(_BidirectionalIter, _Mutable_BidirectionalIterator);
  408. __STL_REQUIRES(typename iterator_traits<_BidirectionalIter>::value_type,
  409. _LessThanComparable);
  410. if (__first == __middle || __middle == __last)//若有空序列,则之间返回
  411. return;
  412. __inplace_merge_aux(__first, __middle, __last,
  413. __VALUE_TYPE(__first), __DISTANCE_TYPE(__first));
  414. }
  415. //版本二
  416. template <class _BidirectionalIter, class _Compare>
  417. inline void inplace_merge(_BidirectionalIter __first,
  418. _BidirectionalIter __middle,
  419. _BidirectionalIter __last, _Compare __comp) {
  420. __STL_REQUIRES(_BidirectionalIter, _Mutable_BidirectionalIterator);
  421. __STL_BINARY_FUNCTION_CHECK(_Compare, bool,
  422. typename iterator_traits<_BidirectionalIter>::value_type,
  423. typename iterator_traits<_BidirectionalIter>::value_type);
  424. if (__first == __middle || __middle == __last)
  425. return;
  426. __inplace_merge_aux(__first, __middle, __last,
  427. __VALUE_TYPE(__first), __DISTANCE_TYPE(__first),
  428. __comp);
  429. }
  430. //inplace_merge函数举例:
  431. /*
  432. #include <iostream> // std::cout
  433. #include <algorithm> // std::inplace_merge, std::sort, std::copy
  434. #include <vector> // std::vector
  435. int main () {
  436. int first[] = {5,10,15,20,25};
  437. int second[] = {50,40,30,20,10};
  438. std::vector<int> v(10);
  439. std::vector<int>::iterator it;
  440. std::sort (first,first+5);
  441. std::sort (second,second+5);
  442. it=std::copy (first, first+5, v.begin());
  443. std::copy (second,second+5,it);
  444. std::inplace_merge (v.begin(),v.begin()+5,v.end());
  445. std::cout << "The resulting vector contains:";
  446. for (it=v.begin(); it!=v.end(); ++it)
  447. std::cout << ' ' << *it;
  448. std::cout << '\n';
  449. return 0;
  450. }
  451. Output:
  452. The resulting vector contains: 5 10 10 15 20 20 25 30 40 50
  453. */

参考资料:

《STL源码剖析》侯捷

发表评论

表情:
评论列表 (有 0 条评论,432人围观)

还没有评论,来说两句吧...

相关阅读

    相关 STL剖析】Sort算法

    前言:sort算法必须拿出来单独将,因为它是STL所有算法中最复杂最庞大的一个,就像我肯定会把copy算法单独列出来一样,这两个算法太重要了。 提示:STL算法特点是,前两个