UNPKG

astl

Version:

AssemblyScript-STL (Standard Template Library, migrated from the C++)

149 lines (137 loc) 4.74 kB
import { advance, distance } from "../iterator/global"; /* ========================================================= EA-STL (https://github.com/electronicarts/EASTL/blob/master/include/EASTL/heap.h) - PUSH & POP - SORT - INTERNAL ============================================================ PUSH & POP --------------------------------------------------------- */ export function make_heap<RandomAccessIterator, Comparator> (first: RandomAccessIterator, last: RandomAccessIterator, comp: Comparator): void { const heapSize: usize = distance(first, last); if (heapSize < 2) return; let parentPosition: usize = ((heapSize - 2) >> 1) + 1; do { const temp = first.advance(--parentPosition).value; _Adjust_heap(first, parentPosition, heapSize, parentPosition, temp, comp); } while (parentPosition !== 0); } export function push_heap<RandomAccessIterator, Comparator> ( first: RandomAccessIterator, last: RandomAccessIterator, comp: Comparator ): void { const temp = last.prev().value; _Promote_heap(first, 0, distance(first, last) - 1, temp, comp); } /** * Pop an element from heap. * * @param first Random access iteartor of the first position. * @param last Random access iterator of the last position. * @param comp A binary function predicates *x* element would be placed before *y*. When returns `true`, then *x* precedes *y*. Default is {@link less}. */ export function pop_heap<RandomAccessIterator, Comparator> ( first: RandomAccessIterator, last: RandomAccessIterator, comp: Comparator ): void { const bottom = last.prev(); const temp = bottom.value; bottom.value = first.value; _Adjust_heap(first, 0, distance(first, last) - 1, 0, temp, comp); } /* --------------------------------------------------------- SORT --------------------------------------------------------- */ export function is_heap<RandomAccessIterator, Comparator> ( first: RandomAccessIterator, last: RandomAccessIterator, comp: Comparator ): boolean { const it: RandomAccessIterator = is_heap_until(first, last, comp); return it == last; } export function is_heap_until<RandomAccessIterator, Comparator> ( first: RandomAccessIterator, last: RandomAccessIterator, comp: Comparator ): RandomAccessIterator { let counter: isize = 0; for (let child = first.next(); child < last; child = child.next(), counter ^= 1) { if (comp(first.value, child.value)) return child; first = advance(first, counter); } return last; } export function sort_heap<RandomAccessIterator, Comparator> ( first: RandomAccessIterator, last: RandomAccessIterator, comp: Comparator ): void { for (; distance(first, last) > 1; last = last.prev()) pop_heap<RandomAccessIterator, Comparator>(first, last, comp); } /* --------------------------------------------------------- INTERNAL --------------------------------------------------------- */ function _Promote_heap<RandomAccessIterator, T, Comparator> ( first: RandomAccessIterator, topPosition: usize, position: usize, value: T, comp: Comparator ): void { for (let parentPosition: usize = (position - 1) >> 1; (position > topPosition) && comp(first.advance(parentPosition).value, value); parentPosition = (position - 1) >> 1) { first.advance(position).value = first.advance(parentPosition).value; position = parentPosition; } first.advance(position).value = value; } function _Adjust_heap<RandomAccessIterator, T, Comparator> ( first: RandomAccessIterator, topPosition: usize, heapSize: usize, position: usize, value: T, comp: Comparator ): void { let childPosition: usize = (2 * position) + 2; for (; childPosition < heapSize; childPosition = (2 * childPosition) + 2) { if (comp(first.advance(childPosition).value, first.advance(childPosition - 1).value)) --childPosition; first.advance(position).value = first.advance(childPosition).value; position = childPosition; } if (childPosition === heapSize) { first.advance(position).value = first.advance(childPosition - 1).value; position = childPosition - 1; } _Promote_heap(first, topPosition, position, value, comp); }