diff --git a/lib/data_structures/heap.dart b/lib/data_structures/heap.dart new file mode 100644 index 0000000..b7b9d05 --- /dev/null +++ b/lib/data_structures/heap.dart @@ -0,0 +1,83 @@ +class Heap { + + final int Function(T) getPriority; + List<(T, int)> _items; + + Heap({ + required this.getPriority + }): _items = []; + + factory Heap.fromItems( + List items, + { + required int Function(T) getPriority, + } + ) { + Heap 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(); + +} \ No newline at end of file