From a22d229c0179f2096d6a9bc929401a25d64384f9 Mon Sep 17 00:00:00 2001 From: Dany Thach Date: Sat, 15 Feb 2025 19:40:47 +0100 Subject: [PATCH] Fix: heap sift-down to the right happened even when it shouldn't have --- lib/data_structures/search_heap.dart | 53 +++++++++++++++++++--------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/lib/data_structures/search_heap.dart b/lib/data_structures/search_heap.dart index b44d87c..f0b4d63 100644 --- a/lib/data_structures/search_heap.dart +++ b/lib/data_structures/search_heap.dart @@ -3,14 +3,14 @@ class SearchHeap { final K Function(T) getKey; final int Function(T) getPriority; List<(T, K, int)> _items; - Map _positionByKey; + Map _indexByKey; SearchHeap({ required this.getKey, required this.getPriority, }): _items = [], - _positionByKey = {}; + _indexByKey = {}; factory SearchHeap.fromItems( List items, @@ -43,11 +43,11 @@ class SearchHeap { _items.add(heapItem); while (i > 0 && _items[(i-1) >> 1].$3 > thisKey) { _items[i] = _items[(i-1) >> 1]; - _positionByKey[_items[i].$2] = i; + _indexByKey[_items[i].$2] = i; i = (i-1) >> 1; } _items[i] = heapItem; - _positionByKey[heapItem.$2] = i; + _indexByKey[heapItem.$2] = i; } T removeFirst() { @@ -55,7 +55,7 @@ class SearchHeap { throw StateError("No element"); } final T firstItem = _items[0].$1; - _positionByKey.remove(_items[0].$2); + _indexByKey.remove(_items[0].$2); if (_items.length < 2) { _items.length--; return firstItem; @@ -71,34 +71,34 @@ class SearchHeap { if (leftIndex < _items.length && itemToMove.$3 > _items[leftIndex].$3) { if (rightIndex < _items.length && _items[leftIndex].$3 > _items[rightIndex].$3) { _items[i] = _items[rightIndex]; - _positionByKey[_items[i].$2] = i; + _indexByKey[_items[i].$2] = i; i = rightIndex; } else { _items[i] = _items[leftIndex]; - _positionByKey[_items[i].$2] = i; + _indexByKey[_items[i].$2] = i; i = leftIndex; } - } else if (rightIndex < _items.length && _items[leftIndex].$3 > _items[rightIndex].$3) { + } else if (rightIndex < _items.length && itemToMove.$3 > _items[rightIndex].$3) { _items[i] = _items[rightIndex]; - _positionByKey[_items[i].$2] = i; + _indexByKey[_items[i].$2] = i; i = rightIndex; } else { stop = true; } } _items[i] = itemToMove; - _positionByKey[itemToMove.$2] = i; + _indexByKey[itemToMove.$2] = i; return firstItem; } void updateElement(K key) { - int i = _positionByKey[key]!; + int i = _indexByKey[key]!; final (T, K, int) item = (_items[i].$1, _items[i].$2, getPriority(_items[i].$1)); bool dontBubbleDown = false; while (i > 0 && _items[(i-1) >> 1].$3 > item.$3) { dontBubbleDown = true; _items[i] = _items[(i-1) >> 1]; - _positionByKey[_items[i].$2] = i; + _indexByKey[_items[i].$2] = i; i = (i-1) >> 1; } int leftIndex, rightIndex; @@ -108,28 +108,47 @@ class SearchHeap { if (leftIndex < _items.length && item.$3 > _items[leftIndex].$3) { if (rightIndex < _items.length && _items[leftIndex].$3 > _items[rightIndex].$3) { _items[i] = _items[rightIndex]; - _positionByKey[_items[i].$2] = i; + _indexByKey[_items[i].$2] = i; i = rightIndex; } else { _items[i] = _items[leftIndex]; - _positionByKey[_items[i].$2] = i; + _indexByKey[_items[i].$2] = i; i = leftIndex; } - } else if (rightIndex < _items.length && _items[leftIndex].$3 > _items[rightIndex].$3) { + } else if (rightIndex < _items.length && item.$3 > _items[rightIndex].$3) { _items[i] = _items[rightIndex]; - _positionByKey[_items[i].$2] = i; + _indexByKey[_items[i].$2] = i; i = rightIndex; } else { dontBubbleDown = true; } } _items[i] = item; - _positionByKey[item.$2] = i; + _indexByKey[item.$2] = i; } @override String toString() => _items.map(((T, K, int) item) => item.$1).toString(); List get debugItems => _items.map(((T, K, int) item) => item.$1).toList(); + Map get debugPositionByKey => _indexByKey; + + bool get debugHeapValidity { + for (int i = 1; i < _items.length; i++) { + if (_items[i].$3 < _items[(i-1) >> 1].$3) { + return false; + } + } + return true; + } + + bool get debugDictionaryValidity { + for (final MapEntry(key: K key, value: int index) in _indexByKey.entries) { + if (_items[index].$2 != key) { + return false; + } + } + return true; + } } \ No newline at end of file