You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

584 lines
20KB

  1. // Heap implementation -*- C++ -*-
  2. // Copyright (C) 2001-2020 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. _GLIBCXX20_CONSTEXPR
  63. _Distance
  64. __is_heap_until(_RandomAccessIterator __first, _Distance __n,
  65. _Compare& __comp)
  66. {
  67. _Distance __parent = 0;
  68. for (_Distance __child = 1; __child < __n; ++__child)
  69. {
  70. if (__comp(__first + __parent, __first + __child))
  71. return __child;
  72. if ((__child & 1) == 0)
  73. ++__parent;
  74. }
  75. return __n;
  76. }
  77. // __is_heap, a predicate testing whether or not a range is a heap.
  78. // This function is an extension, not part of the C++ standard.
  79. template<typename _RandomAccessIterator, typename _Distance>
  80. _GLIBCXX20_CONSTEXPR
  81. inline bool
  82. __is_heap(_RandomAccessIterator __first, _Distance __n)
  83. {
  84. __gnu_cxx::__ops::_Iter_less_iter __comp;
  85. return std::__is_heap_until(__first, __n, __comp) == __n;
  86. }
  87. template<typename _RandomAccessIterator, typename _Compare,
  88. typename _Distance>
  89. _GLIBCXX20_CONSTEXPR
  90. inline bool
  91. __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
  92. {
  93. typedef __decltype(__comp) _Cmp;
  94. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  95. return std::__is_heap_until(__first, __n, __cmp) == __n;
  96. }
  97. template<typename _RandomAccessIterator>
  98. _GLIBCXX20_CONSTEXPR
  99. inline bool
  100. __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  101. { return std::__is_heap(__first, std::distance(__first, __last)); }
  102. template<typename _RandomAccessIterator, typename _Compare>
  103. _GLIBCXX20_CONSTEXPR
  104. inline bool
  105. __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  106. _Compare __comp)
  107. {
  108. return std::__is_heap(__first, _GLIBCXX_MOVE(__comp),
  109. std::distance(__first, __last));
  110. }
  111. // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
  112. // + is_heap and is_heap_until in C++0x.
  113. template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
  114. typename _Compare>
  115. _GLIBCXX20_CONSTEXPR
  116. void
  117. __push_heap(_RandomAccessIterator __first,
  118. _Distance __holeIndex, _Distance __topIndex, _Tp __value,
  119. _Compare& __comp)
  120. {
  121. _Distance __parent = (__holeIndex - 1) / 2;
  122. while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
  123. {
  124. *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
  125. __holeIndex = __parent;
  126. __parent = (__holeIndex - 1) / 2;
  127. }
  128. *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
  129. }
  130. /**
  131. * @brief Push an element onto a heap.
  132. * @param __first Start of heap.
  133. * @param __last End of heap + element.
  134. * @ingroup heap_algorithms
  135. *
  136. * This operation pushes the element at last-1 onto the valid heap
  137. * over the range [__first,__last-1). After completion,
  138. * [__first,__last) is a valid heap.
  139. */
  140. template<typename _RandomAccessIterator>
  141. _GLIBCXX20_CONSTEXPR
  142. inline void
  143. push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  144. {
  145. typedef typename iterator_traits<_RandomAccessIterator>::value_type
  146. _ValueType;
  147. typedef typename iterator_traits<_RandomAccessIterator>::difference_type
  148. _DistanceType;
  149. // concept requirements
  150. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  151. _RandomAccessIterator>)
  152. __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
  153. __glibcxx_requires_valid_range(__first, __last);
  154. __glibcxx_requires_irreflexive(__first, __last);
  155. __glibcxx_requires_heap(__first, __last - 1);
  156. __gnu_cxx::__ops::_Iter_less_val __comp;
  157. _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
  158. std::__push_heap(__first, _DistanceType((__last - __first) - 1),
  159. _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
  160. }
  161. /**
  162. * @brief Push an element onto a heap using comparison functor.
  163. * @param __first Start of heap.
  164. * @param __last End of heap + element.
  165. * @param __comp Comparison functor.
  166. * @ingroup heap_algorithms
  167. *
  168. * This operation pushes the element at __last-1 onto the valid
  169. * heap over the range [__first,__last-1). After completion,
  170. * [__first,__last) is a valid heap. Compare operations are
  171. * performed using comp.
  172. */
  173. template<typename _RandomAccessIterator, typename _Compare>
  174. _GLIBCXX20_CONSTEXPR
  175. inline void
  176. push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  177. _Compare __comp)
  178. {
  179. typedef typename iterator_traits<_RandomAccessIterator>::value_type
  180. _ValueType;
  181. typedef typename iterator_traits<_RandomAccessIterator>::difference_type
  182. _DistanceType;
  183. // concept requirements
  184. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  185. _RandomAccessIterator>)
  186. __glibcxx_requires_valid_range(__first, __last);
  187. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  188. __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
  189. __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
  190. __cmp(_GLIBCXX_MOVE(__comp));
  191. _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
  192. std::__push_heap(__first, _DistanceType((__last - __first) - 1),
  193. _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp);
  194. }
  195. template<typename _RandomAccessIterator, typename _Distance,
  196. typename _Tp, typename _Compare>
  197. _GLIBCXX20_CONSTEXPR
  198. void
  199. __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
  200. _Distance __len, _Tp __value, _Compare __comp)
  201. {
  202. const _Distance __topIndex = __holeIndex;
  203. _Distance __secondChild = __holeIndex;
  204. while (__secondChild < (__len - 1) / 2)
  205. {
  206. __secondChild = 2 * (__secondChild + 1);
  207. if (__comp(__first + __secondChild,
  208. __first + (__secondChild - 1)))
  209. __secondChild--;
  210. *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
  211. __holeIndex = __secondChild;
  212. }
  213. if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
  214. {
  215. __secondChild = 2 * (__secondChild + 1);
  216. *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
  217. + (__secondChild - 1)));
  218. __holeIndex = __secondChild - 1;
  219. }
  220. __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
  221. __cmp(_GLIBCXX_MOVE(__comp));
  222. std::__push_heap(__first, __holeIndex, __topIndex,
  223. _GLIBCXX_MOVE(__value), __cmp);
  224. }
  225. template<typename _RandomAccessIterator, typename _Compare>
  226. _GLIBCXX20_CONSTEXPR
  227. inline void
  228. __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  229. _RandomAccessIterator __result, _Compare& __comp)
  230. {
  231. typedef typename iterator_traits<_RandomAccessIterator>::value_type
  232. _ValueType;
  233. typedef typename iterator_traits<_RandomAccessIterator>::difference_type
  234. _DistanceType;
  235. _ValueType __value = _GLIBCXX_MOVE(*__result);
  236. *__result = _GLIBCXX_MOVE(*__first);
  237. std::__adjust_heap(__first, _DistanceType(0),
  238. _DistanceType(__last - __first),
  239. _GLIBCXX_MOVE(__value), __comp);
  240. }
  241. /**
  242. * @brief Pop an element off a heap.
  243. * @param __first Start of heap.
  244. * @param __last End of heap.
  245. * @pre [__first, __last) is a valid, non-empty range.
  246. * @ingroup heap_algorithms
  247. *
  248. * This operation pops the top of the heap. The elements __first
  249. * and __last-1 are swapped and [__first,__last-1) is made into a
  250. * heap.
  251. */
  252. template<typename _RandomAccessIterator>
  253. _GLIBCXX20_CONSTEXPR
  254. inline void
  255. pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  256. {
  257. // concept requirements
  258. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  259. _RandomAccessIterator>)
  260. __glibcxx_function_requires(_LessThanComparableConcept<
  261. typename iterator_traits<_RandomAccessIterator>::value_type>)
  262. __glibcxx_requires_non_empty_range(__first, __last);
  263. __glibcxx_requires_valid_range(__first, __last);
  264. __glibcxx_requires_irreflexive(__first, __last);
  265. __glibcxx_requires_heap(__first, __last);
  266. if (__last - __first > 1)
  267. {
  268. --__last;
  269. __gnu_cxx::__ops::_Iter_less_iter __comp;
  270. std::__pop_heap(__first, __last, __last, __comp);
  271. }
  272. }
  273. /**
  274. * @brief Pop an element off a heap using comparison functor.
  275. * @param __first Start of heap.
  276. * @param __last End of heap.
  277. * @param __comp Comparison functor to use.
  278. * @ingroup heap_algorithms
  279. *
  280. * This operation pops the top of the heap. The elements __first
  281. * and __last-1 are swapped and [__first,__last-1) is made into a
  282. * heap. Comparisons are made using comp.
  283. */
  284. template<typename _RandomAccessIterator, typename _Compare>
  285. _GLIBCXX20_CONSTEXPR
  286. inline void
  287. pop_heap(_RandomAccessIterator __first,
  288. _RandomAccessIterator __last, _Compare __comp)
  289. {
  290. // concept requirements
  291. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  292. _RandomAccessIterator>)
  293. __glibcxx_requires_valid_range(__first, __last);
  294. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  295. __glibcxx_requires_non_empty_range(__first, __last);
  296. __glibcxx_requires_heap_pred(__first, __last, __comp);
  297. if (__last - __first > 1)
  298. {
  299. typedef __decltype(__comp) _Cmp;
  300. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  301. --__last;
  302. std::__pop_heap(__first, __last, __last, __cmp);
  303. }
  304. }
  305. template<typename _RandomAccessIterator, typename _Compare>
  306. _GLIBCXX20_CONSTEXPR
  307. void
  308. __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  309. _Compare& __comp)
  310. {
  311. typedef typename iterator_traits<_RandomAccessIterator>::value_type
  312. _ValueType;
  313. typedef typename iterator_traits<_RandomAccessIterator>::difference_type
  314. _DistanceType;
  315. if (__last - __first < 2)
  316. return;
  317. const _DistanceType __len = __last - __first;
  318. _DistanceType __parent = (__len - 2) / 2;
  319. while (true)
  320. {
  321. _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
  322. std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
  323. __comp);
  324. if (__parent == 0)
  325. return;
  326. __parent--;
  327. }
  328. }
  329. /**
  330. * @brief Construct a heap over a range.
  331. * @param __first Start of heap.
  332. * @param __last End of heap.
  333. * @ingroup heap_algorithms
  334. *
  335. * This operation makes the elements in [__first,__last) into a heap.
  336. */
  337. template<typename _RandomAccessIterator>
  338. _GLIBCXX20_CONSTEXPR
  339. inline void
  340. make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  341. {
  342. // concept requirements
  343. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  344. _RandomAccessIterator>)
  345. __glibcxx_function_requires(_LessThanComparableConcept<
  346. typename iterator_traits<_RandomAccessIterator>::value_type>)
  347. __glibcxx_requires_valid_range(__first, __last);
  348. __glibcxx_requires_irreflexive(__first, __last);
  349. __gnu_cxx::__ops::_Iter_less_iter __comp;
  350. std::__make_heap(__first, __last, __comp);
  351. }
  352. /**
  353. * @brief Construct a heap over a range using comparison functor.
  354. * @param __first Start of heap.
  355. * @param __last End of heap.
  356. * @param __comp Comparison functor to use.
  357. * @ingroup heap_algorithms
  358. *
  359. * This operation makes the elements in [__first,__last) into a heap.
  360. * Comparisons are made using __comp.
  361. */
  362. template<typename _RandomAccessIterator, typename _Compare>
  363. _GLIBCXX20_CONSTEXPR
  364. inline void
  365. make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  366. _Compare __comp)
  367. {
  368. // concept requirements
  369. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  370. _RandomAccessIterator>)
  371. __glibcxx_requires_valid_range(__first, __last);
  372. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  373. typedef __decltype(__comp) _Cmp;
  374. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  375. std::__make_heap(__first, __last, __cmp);
  376. }
  377. template<typename _RandomAccessIterator, typename _Compare>
  378. _GLIBCXX20_CONSTEXPR
  379. void
  380. __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  381. _Compare& __comp)
  382. {
  383. while (__last - __first > 1)
  384. {
  385. --__last;
  386. std::__pop_heap(__first, __last, __last, __comp);
  387. }
  388. }
  389. /**
  390. * @brief Sort a heap.
  391. * @param __first Start of heap.
  392. * @param __last End of heap.
  393. * @ingroup heap_algorithms
  394. *
  395. * This operation sorts the valid heap in the range [__first,__last).
  396. */
  397. template<typename _RandomAccessIterator>
  398. _GLIBCXX20_CONSTEXPR
  399. inline void
  400. sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  401. {
  402. // concept requirements
  403. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  404. _RandomAccessIterator>)
  405. __glibcxx_function_requires(_LessThanComparableConcept<
  406. typename iterator_traits<_RandomAccessIterator>::value_type>)
  407. __glibcxx_requires_valid_range(__first, __last);
  408. __glibcxx_requires_irreflexive(__first, __last);
  409. __glibcxx_requires_heap(__first, __last);
  410. __gnu_cxx::__ops::_Iter_less_iter __comp;
  411. std::__sort_heap(__first, __last, __comp);
  412. }
  413. /**
  414. * @brief Sort a heap using comparison functor.
  415. * @param __first Start of heap.
  416. * @param __last End of heap.
  417. * @param __comp Comparison functor to use.
  418. * @ingroup heap_algorithms
  419. *
  420. * This operation sorts the valid heap in the range [__first,__last).
  421. * Comparisons are made using __comp.
  422. */
  423. template<typename _RandomAccessIterator, typename _Compare>
  424. _GLIBCXX20_CONSTEXPR
  425. inline void
  426. sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  427. _Compare __comp)
  428. {
  429. // concept requirements
  430. __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  431. _RandomAccessIterator>)
  432. __glibcxx_requires_valid_range(__first, __last);
  433. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  434. __glibcxx_requires_heap_pred(__first, __last, __comp);
  435. typedef __decltype(__comp) _Cmp;
  436. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  437. std::__sort_heap(__first, __last, __cmp);
  438. }
  439. #if __cplusplus >= 201103L
  440. /**
  441. * @brief Search the end of a heap.
  442. * @param __first Start of range.
  443. * @param __last End of range.
  444. * @return An iterator pointing to the first element not in the heap.
  445. * @ingroup heap_algorithms
  446. *
  447. * This operation returns the last iterator i in [__first, __last) for which
  448. * the range [__first, i) is a heap.
  449. */
  450. template<typename _RandomAccessIterator>
  451. _GLIBCXX20_CONSTEXPR
  452. inline _RandomAccessIterator
  453. is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
  454. {
  455. // concept requirements
  456. __glibcxx_function_requires(_RandomAccessIteratorConcept<
  457. _RandomAccessIterator>)
  458. __glibcxx_function_requires(_LessThanComparableConcept<
  459. typename iterator_traits<_RandomAccessIterator>::value_type>)
  460. __glibcxx_requires_valid_range(__first, __last);
  461. __glibcxx_requires_irreflexive(__first, __last);
  462. __gnu_cxx::__ops::_Iter_less_iter __comp;
  463. return __first +
  464. std::__is_heap_until(__first, std::distance(__first, __last), __comp);
  465. }
  466. /**
  467. * @brief Search the end of a heap using comparison functor.
  468. * @param __first Start of range.
  469. * @param __last End of range.
  470. * @param __comp Comparison functor to use.
  471. * @return An iterator pointing to the first element not in the heap.
  472. * @ingroup heap_algorithms
  473. *
  474. * This operation returns the last iterator i in [__first, __last) for which
  475. * the range [__first, i) is a heap. Comparisons are made using __comp.
  476. */
  477. template<typename _RandomAccessIterator, typename _Compare>
  478. _GLIBCXX20_CONSTEXPR
  479. inline _RandomAccessIterator
  480. is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last,
  481. _Compare __comp)
  482. {
  483. // concept requirements
  484. __glibcxx_function_requires(_RandomAccessIteratorConcept<
  485. _RandomAccessIterator>)
  486. __glibcxx_requires_valid_range(__first, __last);
  487. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  488. typedef __decltype(__comp) _Cmp;
  489. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  490. return __first
  491. + std::__is_heap_until(__first, std::distance(__first, __last), __cmp);
  492. }
  493. /**
  494. * @brief Determines whether a range is a heap.
  495. * @param __first Start of range.
  496. * @param __last End of range.
  497. * @return True if range is a heap, false otherwise.
  498. * @ingroup heap_algorithms
  499. */
  500. template<typename _RandomAccessIterator>
  501. _GLIBCXX20_CONSTEXPR
  502. inline bool
  503. is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
  504. { return std::is_heap_until(__first, __last) == __last; }
  505. /**
  506. * @brief Determines whether a range is a heap using comparison functor.
  507. * @param __first Start of range.
  508. * @param __last End of range.
  509. * @param __comp Comparison functor to use.
  510. * @return True if range is a heap, false otherwise.
  511. * @ingroup heap_algorithms
  512. */
  513. template<typename _RandomAccessIterator, typename _Compare>
  514. _GLIBCXX20_CONSTEXPR
  515. inline bool
  516. is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
  517. _Compare __comp)
  518. {
  519. // concept requirements
  520. __glibcxx_function_requires(_RandomAccessIteratorConcept<
  521. _RandomAccessIterator>)
  522. __glibcxx_requires_valid_range(__first, __last);
  523. __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
  524. const auto __dist = std::distance(__first, __last);
  525. typedef __decltype(__comp) _Cmp;
  526. __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
  527. return std::__is_heap_until(__first, __dist, __cmp) == __dist;
  528. }
  529. #endif
  530. _GLIBCXX_END_NAMESPACE_VERSION
  531. } // namespace
  532. #endif /* _STL_HEAP_H */