Path: blob/master/thirdparty/jolt_physics/Jolt/Core/BinaryHeap.h
9906 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2024 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#pragma once56JPH_NAMESPACE_BEGIN78/// Push a new element into a binary max-heap.9/// [inBegin, inEnd - 1) must be a a valid heap. Element inEnd - 1 will be inserted into the heap. The heap will be [inBegin, inEnd) after this call.10/// inPred is a function that returns true if the first element is less or equal than the second element.11/// See: https://en.wikipedia.org/wiki/Binary_heap12template <typename Iterator, typename Pred>13void BinaryHeapPush(Iterator inBegin, Iterator inEnd, Pred inPred)14{15using diff_t = typename std::iterator_traits<Iterator>::difference_type;16using elem_t = typename std::iterator_traits<Iterator>::value_type;1718// New heap size19diff_t count = std::distance(inBegin, inEnd);2021// Start from the last element22diff_t current = count - 1;23while (current > 0)24{25// Get current element26elem_t ¤t_elem = *(inBegin + current);2728// Get parent element29diff_t parent = (current - 1) >> 1;30elem_t &parent_elem = *(inBegin + parent);3132// Sort them so that the parent is larger than the child33if (inPred(parent_elem, current_elem))34{35std::swap(parent_elem, current_elem);36current = parent;37}38else39{40// When there's no change, we're done41break;42}43}44}4546/// Pop an element from a binary max-heap.47/// [inBegin, inEnd) must be a valid heap. The largest element will be removed from the heap. The heap will be [inBegin, inEnd - 1) after this call.48/// inPred is a function that returns true if the first element is less or equal than the second element.49/// See: https://en.wikipedia.org/wiki/Binary_heap50template <typename Iterator, typename Pred>51void BinaryHeapPop(Iterator inBegin, Iterator inEnd, Pred inPred)52{53using diff_t = typename std::iterator_traits<Iterator>::difference_type;5455// Begin by moving the highest element to the end, this is the popped element56std::swap(*(inEnd - 1), *inBegin);5758// New heap size59diff_t count = std::distance(inBegin, inEnd) - 1;6061// Start from the root62diff_t largest = 0;63for (;;)64{65// Get first child66diff_t child = (largest << 1) + 1;6768// Check if we're beyond the end of the heap, if so the 2nd child is also beyond the end69if (child >= count)70break;7172// Remember the largest element from the previous iteration73diff_t prev_largest = largest;7475// Check if first child is bigger, if so select it76if (inPred(*(inBegin + largest), *(inBegin + child)))77largest = child;7879// Switch to the second child80++child;8182// Check if second child is bigger, if so select it83if (child < count && inPred(*(inBegin + largest), *(inBegin + child)))84largest = child;8586// If there was no change, we're done87if (prev_largest == largest)88break;8990// Swap element91std::swap(*(inBegin + prev_largest), *(inBegin + largest));92}93}9495JPH_NAMESPACE_END969798