omnichess/lib/data_structures/heap.dart

83 lines
1.9 KiB
Dart

class Heap<T> {
final int Function(T) getPriority;
List<(T, int)> _items;
Heap({
required this.getPriority
}): _items = [];
factory Heap.fromItems(
List<T> items,
{
required int Function(T) getPriority,
}
) {
Heap<T> heap = Heap(getPriority: getPriority);
for (final T item in items) {
heap.add(item);
}
return heap;
}
T get first => _items.first.$1;
T? get firstOrNull => _items.firstOrNull?.$1;
int get length => _items.length;
bool get isEmpty => _items.isEmpty;
bool get isNotEmpty => _items.isNotEmpty;
void add(T item) {
final (T, int) heapItem = (item, getPriority(item));
final int thisKey = heapItem.$2;
int i = _items.length;
_items.add(heapItem);
while (i > 0 && _items[(i-1) ~/ 2].$2 > thisKey) {
_items[i] = _items[(i-1) ~/ 2];
i = (i-1)~/2;
}
_items[i] = heapItem;
}
T removeFirst() {
if (_items.isEmpty) {
throw StateError("No element");
}
final T firstItem = _items[0].$1;
if (_items.length < 2) {
_items.length--;
return firstItem;
}
final (T, int) itemToMove = _items.last;
_items[0] = itemToMove;
_items.length--;
int i = 0;
int leftIndex, rightIndex;
bool stop = false;
while (!stop) {
rightIndex = (i+1) << 1;
leftIndex = rightIndex-1;
if (leftIndex < _items.length && itemToMove.$2 > _items[leftIndex].$2) {
if (rightIndex < _items.length && _items[leftIndex].$2 > _items[rightIndex].$2) {
_items[i] = _items[rightIndex];
_items[rightIndex] = itemToMove;
i = rightIndex;
} else {
_items[i] = _items[leftIndex];
_items[leftIndex] = itemToMove;
i = leftIndex;
}
} else {
stop = true;
}
}
return firstItem;
}
@override
String toString() => _items.map(((T, int) item) => item.$1).toString();
}