| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| /// Basic implementation of a heap, with O(log n) insertion and removal. | |
| abstract class Heap<T> { | |
| final _items = <T>[]; | |
| bool get isEmpty => _items.isEmpty; | |
| bool get isNotEmpty => _items.isNotEmpty; | |
| void add(T item) { | |
| int index = _items.length; | |
| _items.add(item); | |
| while (index > 0) { | |
| T parent = _items[_parentIndex(index)]; | |
| if (sortsBefore(parent, item)) break; | |
| _items[index] = parent; | |
| index = _parentIndex(index); | |
| } | |
| _items[index] = item; | |
| } | |
| T remove() { | |
| T removed = _items[0]; | |
| T orphan = _items.removeLast(); | |
| if (_items.isNotEmpty) _reInsert(orphan); | |
| return removed; | |
| } | |
| /// Client should use a derived class to specify the sort order. | |
| bool sortsBefore(T a, T b); | |
| int _firstChildIndex(int index) { | |
| return (index << 1) + 1; | |
| } | |
| int _parentIndex(int index) { | |
| return (index - 1) >> 1; | |
| } | |
| void _reInsert(T item) { | |
| int index = 0; | |
| while (true) { | |
| int childIndex = _firstChildIndex(index); | |
| if (childIndex >= _items.length) break; | |
| T child = _items[childIndex]; | |
| if (childIndex + 1 < _items.length) { | |
| T nextChild = _items[childIndex + 1]; | |
| if (sortsBefore(nextChild, child)) { | |
| child = nextChild; | |
| childIndex++; | |
| } | |
| } | |
| if (sortsBefore(item, child)) break; | |
| _items[index] = _items[childIndex]; | |
| index = childIndex; | |
| } | |
| _items[index] = item; | |
| } | |
| } |