stl_heap.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. // Heap implementation -*- C++ -*-
  2. // Copyright (C) 2001-2018 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /*
  21. *
  22. * Copyright (c) 1994
  23. * Hewlett-Packard Company
  24. *
  25. * Permission to use, copy, modify, distribute and sell this software
  26. * and its documentation for any purpose is hereby granted without fee,
  27. * provided that the above copyright notice appear in all copies and
  28. * that both that copyright notice and this permission notice appear
  29. * in supporting documentation. Hewlett-Packard Company makes no
  30. * representations about the suitability of this software for any
  31. * purpose. It is provided "as is" without express or implied warranty.
  32. *
  33. * Copyright (c) 1997
  34. * Silicon Graphics Computer Systems, Inc.
  35. *
  36. * Permission to use, copy, modify, distribute and sell this software
  37. * and its documentation for any purpose is hereby granted without fee,
  38. * provided that the above copyright notice appear in all copies and
  39. * that both that copyright notice and this permission notice appear
  40. * in supporting documentation. Silicon Graphics makes no
  41. * representations about the suitability of this software for any
  42. * purpose. It is provided "as is" without express or implied warranty.
  43. */
  44. /** @file bits/stl_heap.h
  45. * This is an internal header file, included by other library headers.
  46. * Do not attempt to use it directly. @headername{queue}
  47. */
  48. #ifndef _STL_HEAP_H
  49. #define _STL_HEAP_H 1
  50. #include <debug/debug.h>
  51. #include <bits/move.h>
  52. #include <bits/predefined_ops.h>
  53. namespace std _GLIBCXX_VISIBILITY(default)
  54. {
  55. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  56. /**
  57. * @defgroup heap_algorithms Heap
  58. * @ingroup sorting_algorithms
  59. */
  60. template<typename _RandomAccessIterator, typename _Distance,
  61. typename _Compare>
  62. _Distance
  63. __is_heap_until(_RandomAccessIterator __first, _Distance __n,
  64. _Compare& __comp)
  65. {
  66. _Distance __parent = 0;
  67. for (_Distance __child = 1; __child < __n; ++__child)
  68. {
  69. if (__comp(__first + __parent, __first + __child))
  70. return __child;
  71. if ((__child & 1) == 0)
  72. ++__parent;
  73. }
  74. return __n;
  75. }
  76. // __is_heap, a predicate testing whether or not a range is a heap.
  77. // This function is an extension, not part of the C++ standard.
  78. template<typename _RandomAccessIterator, typename _Distance>
  79. inline bool
  80. __is_heap(_RandomAccessIterator __first, _Distance __n)
  81. {
  82. __gnu_cxx::__ops::_Iter_less_iter __comp;
  83. return std::__is_heap_until(__first, __n, __comp) == __n;
  84. }
  85. template<typename _RandomAccessIterator, typename _Compare,
  86. typename _Distance>
  87. inline bool
  88. __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
  89. {
  90. typedef __decltype(__comp) _Cmp;
  91. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  92. return std::__is_heap_until(__first, __n, __cmp) == __n;
  93. }
  94. template<typename _RandomAccessIterator>
  95. inline bool
  96. __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  97. { return std::__is_heap(__first, std::distance(__first, __last)); }
  98. template<typename _RandomAccessIterator, typename _Compare>
  99. inline bool
  100. __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  101. _Compare __comp)
  102. {
  103. return std::__is_heap(__first, _GLIBCXX_MOVE(__comp),
  104. std::distance(__first, __last));
  105. }
  106. // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
  107. // + is_heap and is_heap_until in C++0x.
  108. template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
  109. typename _Compare>
  110. void
  111. __push_heap(_RandomAccessIterator __first,
  112. _Distance __holeIndex, _Distance __topIndex, _Tp __value,
  113. _Compare& __comp)
  114. {
  115. _Distance __parent = (__holeIndex - 1) / 2;
  116. while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
  117. {
  118. *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
  119. __holeIndex = __parent;
  120. __parent = (__holeIndex - 1) / 2;
  121. }
  122. *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
  123. }
  124. /**
  125. * @brief Push an element onto a heap.
  126. * @param __first Start of heap.
  127. * @param __last End of heap + element.
  128. * @ingroup heap_algorithms
  129. *
  130. * This operation pushes the element at last-1 onto the valid heap
  131. * over the range [__first,__last-1). After completion,
  132. * [__first,__last) is a valid heap.
  133. */
  134. template<typename _RandomAccessIterator>
  135. inline void
  136. push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  137. {
  138. typedef typename iterator_traits<_RandomAccessIterator>::value_type
  139. _ValueType;
  140. typedef typename iterator_traits<_RandomAccessIterator>::difference_type
  141. _DistanceType;
  142. // concept requirements
  143. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  144. _RandomAccessIterator>)
  145. __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
  146. __glibcxx_requires_valid_range(__first, __last);
  147. __glibcxx_requires_irreflexive(__first, __last);
  148. __glibcxx_requires_heap(__first, __last - 1);
  149. __gnu_cxx::__ops::_Iter_less_val __comp;
  150. _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
  151. std::__push_heap(__first, _DistanceType((__last - __first) - 1),
  152. _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
  153. }
  154. /**
  155. * @brief Push an element onto a heap using comparison functor.
  156. * @param __first Start of heap.
  157. * @param __last End of heap + element.
  158. * @param __comp Comparison functor.
  159. * @ingroup heap_algorithms
  160. *
  161. * This operation pushes the element at __last-1 onto the valid
  162. * heap over the range [__first,__last-1). After completion,
  163. * [__first,__last) is a valid heap. Compare operations are
  164. * performed using comp.
  165. */
  166. template<typename _RandomAccessIterator, typename _Compare>
  167. inline void
  168. push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  169. _Compare __comp)
  170. {
  171. typedef typename iterator_traits<_RandomAccessIterator>::value_type
  172. _ValueType;
  173. typedef typename iterator_traits<_RandomAccessIterator>::difference_type
  174. _DistanceType;
  175. // concept requirements
  176. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  177. _RandomAccessIterator>)
  178. __glibcxx_requires_valid_range(__first, __last);
  179. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  180. __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
  181. __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
  182. __cmp(_GLIBCXX_MOVE(__comp));
  183. _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
  184. std::__push_heap(__first, _DistanceType((__last - __first) - 1),
  185. _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp);
  186. }
  187. template<typename _RandomAccessIterator, typename _Distance,
  188. typename _Tp, typename _Compare>
  189. void
  190. __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
  191. _Distance __len, _Tp __value, _Compare __comp)
  192. {
  193. const _Distance __topIndex = __holeIndex;
  194. _Distance __secondChild = __holeIndex;
  195. while (__secondChild < (__len - 1) / 2)
  196. {
  197. __secondChild = 2 * (__secondChild + 1);
  198. if (__comp(__first + __secondChild,
  199. __first + (__secondChild - 1)))
  200. __secondChild--;
  201. *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
  202. __holeIndex = __secondChild;
  203. }
  204. if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
  205. {
  206. __secondChild = 2 * (__secondChild + 1);
  207. *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
  208. + (__secondChild - 1)));
  209. __holeIndex = __secondChild - 1;
  210. }
  211. __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
  212. __cmp(_GLIBCXX_MOVE(__comp));
  213. std::__push_heap(__first, __holeIndex, __topIndex,
  214. _GLIBCXX_MOVE(__value), __cmp);
  215. }
  216. template<typename _RandomAccessIterator, typename _Compare>
  217. inline void
  218. __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  219. _RandomAccessIterator __result, _Compare& __comp)
  220. {
  221. typedef typename iterator_traits<_RandomAccessIterator>::value_type
  222. _ValueType;
  223. typedef typename iterator_traits<_RandomAccessIterator>::difference_type
  224. _DistanceType;
  225. _ValueType __value = _GLIBCXX_MOVE(*__result);
  226. *__result = _GLIBCXX_MOVE(*__first);
  227. std::__adjust_heap(__first, _DistanceType(0),
  228. _DistanceType(__last - __first),
  229. _GLIBCXX_MOVE(__value), __comp);
  230. }
  231. /**
  232. * @brief Pop an element off a heap.
  233. * @param __first Start of heap.
  234. * @param __last End of heap.
  235. * @pre [__first, __last) is a valid, non-empty range.
  236. * @ingroup heap_algorithms
  237. *
  238. * This operation pops the top of the heap. The elements __first
  239. * and __last-1 are swapped and [__first,__last-1) is made into a
  240. * heap.
  241. */
  242. template<typename _RandomAccessIterator>
  243. inline void
  244. pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  245. {
  246. // concept requirements
  247. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  248. _RandomAccessIterator>)
  249. __glibcxx_function_requires(_LessThanComparableConcept<
  250. typename iterator_traits<_RandomAccessIterator>::value_type>)
  251. __glibcxx_requires_non_empty_range(__first, __last);
  252. __glibcxx_requires_valid_range(__first, __last);
  253. __glibcxx_requires_irreflexive(__first, __last);
  254. __glibcxx_requires_heap(__first, __last);
  255. if (__last - __first > 1)
  256. {
  257. --__last;
  258. __gnu_cxx::__ops::_Iter_less_iter __comp;
  259. std::__pop_heap(__first, __last, __last, __comp);
  260. }
  261. }
  262. /**
  263. * @brief Pop an element off a heap using comparison functor.
  264. * @param __first Start of heap.
  265. * @param __last End of heap.
  266. * @param __comp Comparison functor to use.
  267. * @ingroup heap_algorithms
  268. *
  269. * This operation pops the top of the heap. The elements __first
  270. * and __last-1 are swapped and [__first,__last-1) is made into a
  271. * heap. Comparisons are made using comp.
  272. */
  273. template<typename _RandomAccessIterator, typename _Compare>
  274. inline void
  275. pop_heap(_RandomAccessIterator __first,
  276. _RandomAccessIterator __last, _Compare __comp)
  277. {
  278. // concept requirements
  279. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  280. _RandomAccessIterator>)
  281. __glibcxx_requires_valid_range(__first, __last);
  282. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  283. __glibcxx_requires_non_empty_range(__first, __last);
  284. __glibcxx_requires_heap_pred(__first, __last, __comp);
  285. if (__last - __first > 1)
  286. {
  287. typedef __decltype(__comp) _Cmp;
  288. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  289. --__last;
  290. std::__pop_heap(__first, __last, __last, __cmp);
  291. }
  292. }
  293. template<typename _RandomAccessIterator, typename _Compare>
  294. void
  295. __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  296. _Compare& __comp)
  297. {
  298. typedef typename iterator_traits<_RandomAccessIterator>::value_type
  299. _ValueType;
  300. typedef typename iterator_traits<_RandomAccessIterator>::difference_type
  301. _DistanceType;
  302. if (__last - __first < 2)
  303. return;
  304. const _DistanceType __len = __last - __first;
  305. _DistanceType __parent = (__len - 2) / 2;
  306. while (true)
  307. {
  308. _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
  309. std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
  310. __comp);
  311. if (__parent == 0)
  312. return;
  313. __parent--;
  314. }
  315. }
  316. /**
  317. * @brief Construct a heap over a range.
  318. * @param __first Start of heap.
  319. * @param __last End of heap.
  320. * @ingroup heap_algorithms
  321. *
  322. * This operation makes the elements in [__first,__last) into a heap.
  323. */
  324. template<typename _RandomAccessIterator>
  325. inline void
  326. make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  327. {
  328. // concept requirements
  329. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  330. _RandomAccessIterator>)
  331. __glibcxx_function_requires(_LessThanComparableConcept<
  332. typename iterator_traits<_RandomAccessIterator>::value_type>)
  333. __glibcxx_requires_valid_range(__first, __last);
  334. __glibcxx_requires_irreflexive(__first, __last);
  335. __gnu_cxx::__ops::_Iter_less_iter __comp;
  336. std::__make_heap(__first, __last, __comp);
  337. }
  338. /**
  339. * @brief Construct a heap over a range using comparison functor.
  340. * @param __first Start of heap.
  341. * @param __last End of heap.
  342. * @param __comp Comparison functor to use.
  343. * @ingroup heap_algorithms
  344. *
  345. * This operation makes the elements in [__first,__last) into a heap.
  346. * Comparisons are made using __comp.
  347. */
  348. template<typename _RandomAccessIterator, typename _Compare>
  349. inline void
  350. make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  351. _Compare __comp)
  352. {
  353. // concept requirements
  354. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  355. _RandomAccessIterator>)
  356. __glibcxx_requires_valid_range(__first, __last);
  357. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  358. typedef __decltype(__comp) _Cmp;
  359. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  360. std::__make_heap(__first, __last, __cmp);
  361. }
  362. template<typename _RandomAccessIterator, typename _Compare>
  363. void
  364. __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  365. _Compare& __comp)
  366. {
  367. while (__last - __first > 1)
  368. {
  369. --__last;
  370. std::__pop_heap(__first, __last, __last, __comp);
  371. }
  372. }
  373. /**
  374. * @brief Sort a heap.
  375. * @param __first Start of heap.
  376. * @param __last End of heap.
  377. * @ingroup heap_algorithms
  378. *
  379. * This operation sorts the valid heap in the range [__first,__last).
  380. */
  381. template<typename _RandomAccessIterator>
  382. inline void
  383. sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  384. {
  385. // concept requirements
  386. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  387. _RandomAccessIterator>)
  388. __glibcxx_function_requires(_LessThanComparableConcept<
  389. typename iterator_traits<_RandomAccessIterator>::value_type>)
  390. __glibcxx_requires_valid_range(__first, __last);
  391. __glibcxx_requires_irreflexive(__first, __last);
  392. __glibcxx_requires_heap(__first, __last);
  393. __gnu_cxx::__ops::_Iter_less_iter __comp;
  394. std::__sort_heap(__first, __last, __comp);
  395. }
  396. /**
  397. * @brief Sort a heap using comparison functor.
  398. * @param __first Start of heap.
  399. * @param __last End of heap.
  400. * @param __comp Comparison functor to use.
  401. * @ingroup heap_algorithms
  402. *
  403. * This operation sorts the valid heap in the range [__first,__last).
  404. * Comparisons are made using __comp.
  405. */
  406. template<typename _RandomAccessIterator, typename _Compare>
  407. inline void
  408. sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  409. _Compare __comp)
  410. {
  411. // concept requirements
  412. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  413. _RandomAccessIterator>)
  414. __glibcxx_requires_valid_range(__first, __last);
  415. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  416. __glibcxx_requires_heap_pred(__first, __last, __comp);
  417. typedef __decltype(__comp) _Cmp;
  418. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  419. std::__sort_heap(__first, __last, __cmp);
  420. }
  421. #if __cplusplus >= 201103L
  422. /**
  423. * @brief Search the end of a heap.
  424. * @param __first Start of range.
  425. * @param __last End of range.
  426. * @return An iterator pointing to the first element not in the heap.
  427. * @ingroup heap_algorithms
  428. *
  429. * This operation returns the last iterator i in [__first, __last) for which
  430. * the range [__first, i) is a heap.
  431. */
  432. template<typename _RandomAccessIterator>
  433. inline _RandomAccessIterator
  434. is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
  435. {
  436. // concept requirements
  437. __glibcxx_function_requires(_RandomAccessIteratorConcept<
  438. _RandomAccessIterator>)
  439. __glibcxx_function_requires(_LessThanComparableConcept<
  440. typename iterator_traits<_RandomAccessIterator>::value_type>)
  441. __glibcxx_requires_valid_range(__first, __last);
  442. __glibcxx_requires_irreflexive(__first, __last);
  443. __gnu_cxx::__ops::_Iter_less_iter __comp;
  444. return __first +
  445. std::__is_heap_until(__first, std::distance(__first, __last), __comp);
  446. }
  447. /**
  448. * @brief Search the end of a heap using comparison functor.
  449. * @param __first Start of range.
  450. * @param __last End of range.
  451. * @param __comp Comparison functor to use.
  452. * @return An iterator pointing to the first element not in the heap.
  453. * @ingroup heap_algorithms
  454. *
  455. * This operation returns the last iterator i in [__first, __last) for which
  456. * the range [__first, i) is a heap. Comparisons are made using __comp.
  457. */
  458. template<typename _RandomAccessIterator, typename _Compare>
  459. inline _RandomAccessIterator
  460. is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last,
  461. _Compare __comp)
  462. {
  463. // concept requirements
  464. __glibcxx_function_requires(_RandomAccessIteratorConcept<
  465. _RandomAccessIterator>)
  466. __glibcxx_requires_valid_range(__first, __last);
  467. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  468. typedef __decltype(__comp) _Cmp;
  469. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  470. return __first
  471. + std::__is_heap_until(__first, std::distance(__first, __last), __cmp);
  472. }
  473. /**
  474. * @brief Determines whether a range is a heap.
  475. * @param __first Start of range.
  476. * @param __last End of range.
  477. * @return True if range is a heap, false otherwise.
  478. * @ingroup heap_algorithms
  479. */
  480. template<typename _RandomAccessIterator>
  481. inline bool
  482. is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  483. { return std::is_heap_until(__first, __last) == __last; }
  484. /**
  485. * @brief Determines whether a range is a heap using comparison functor.
  486. * @param __first Start of range.
  487. * @param __last End of range.
  488. * @param __comp Comparison functor to use.
  489. * @return True if range is a heap, false otherwise.
  490. * @ingroup heap_algorithms
  491. */
  492. template<typename _RandomAccessIterator, typename _Compare>
  493. inline bool
  494. is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  495. _Compare __comp)
  496. {
  497. // concept requirements
  498. __glibcxx_function_requires(_RandomAccessIteratorConcept<
  499. _RandomAccessIterator>)
  500. __glibcxx_requires_valid_range(__first, __last);
  501. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  502. const auto __dist = std::distance(__first, __last);
  503. typedef __decltype(__comp) _Cmp;
  504. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  505. return std::__is_heap_until(__first, __dist, __cmp) == __dist;
  506. }
  507. #endif
  508. _GLIBCXX_END_NAMESPACE_VERSION
  509. } // namespace
  510. #endif /* _STL_HEAP_H */