Fix: heap sift-down to the right happened even when it shouldn't have
parent
0b88775b0c
commit
a22d229c01
|
|
@ -3,14 +3,14 @@ class SearchHeap<K, T> {
|
||||||
final K Function(T) getKey;
|
final K Function(T) getKey;
|
||||||
final int Function(T) getPriority;
|
final int Function(T) getPriority;
|
||||||
List<(T, K, int)> _items;
|
List<(T, K, int)> _items;
|
||||||
Map<K, int> _positionByKey;
|
Map<K, int> _indexByKey;
|
||||||
|
|
||||||
SearchHeap({
|
SearchHeap({
|
||||||
required this.getKey,
|
required this.getKey,
|
||||||
required this.getPriority,
|
required this.getPriority,
|
||||||
}):
|
}):
|
||||||
_items = [],
|
_items = [],
|
||||||
_positionByKey = {};
|
_indexByKey = {};
|
||||||
|
|
||||||
factory SearchHeap.fromItems(
|
factory SearchHeap.fromItems(
|
||||||
List<T> items,
|
List<T> items,
|
||||||
|
|
@ -43,11 +43,11 @@ class SearchHeap<K, T> {
|
||||||
_items.add(heapItem);
|
_items.add(heapItem);
|
||||||
while (i > 0 && _items[(i-1) >> 1].$3 > thisKey) {
|
while (i > 0 && _items[(i-1) >> 1].$3 > thisKey) {
|
||||||
_items[i] = _items[(i-1) >> 1];
|
_items[i] = _items[(i-1) >> 1];
|
||||||
_positionByKey[_items[i].$2] = i;
|
_indexByKey[_items[i].$2] = i;
|
||||||
i = (i-1) >> 1;
|
i = (i-1) >> 1;
|
||||||
}
|
}
|
||||||
_items[i] = heapItem;
|
_items[i] = heapItem;
|
||||||
_positionByKey[heapItem.$2] = i;
|
_indexByKey[heapItem.$2] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
T removeFirst() {
|
T removeFirst() {
|
||||||
|
|
@ -55,7 +55,7 @@ class SearchHeap<K, T> {
|
||||||
throw StateError("No element");
|
throw StateError("No element");
|
||||||
}
|
}
|
||||||
final T firstItem = _items[0].$1;
|
final T firstItem = _items[0].$1;
|
||||||
_positionByKey.remove(_items[0].$2);
|
_indexByKey.remove(_items[0].$2);
|
||||||
if (_items.length < 2) {
|
if (_items.length < 2) {
|
||||||
_items.length--;
|
_items.length--;
|
||||||
return firstItem;
|
return firstItem;
|
||||||
|
|
@ -71,34 +71,34 @@ class SearchHeap<K, T> {
|
||||||
if (leftIndex < _items.length && itemToMove.$3 > _items[leftIndex].$3) {
|
if (leftIndex < _items.length && itemToMove.$3 > _items[leftIndex].$3) {
|
||||||
if (rightIndex < _items.length && _items[leftIndex].$3 > _items[rightIndex].$3) {
|
if (rightIndex < _items.length && _items[leftIndex].$3 > _items[rightIndex].$3) {
|
||||||
_items[i] = _items[rightIndex];
|
_items[i] = _items[rightIndex];
|
||||||
_positionByKey[_items[i].$2] = i;
|
_indexByKey[_items[i].$2] = i;
|
||||||
i = rightIndex;
|
i = rightIndex;
|
||||||
} else {
|
} else {
|
||||||
_items[i] = _items[leftIndex];
|
_items[i] = _items[leftIndex];
|
||||||
_positionByKey[_items[i].$2] = i;
|
_indexByKey[_items[i].$2] = i;
|
||||||
i = leftIndex;
|
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];
|
_items[i] = _items[rightIndex];
|
||||||
_positionByKey[_items[i].$2] = i;
|
_indexByKey[_items[i].$2] = i;
|
||||||
i = rightIndex;
|
i = rightIndex;
|
||||||
} else {
|
} else {
|
||||||
stop = true;
|
stop = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_items[i] = itemToMove;
|
_items[i] = itemToMove;
|
||||||
_positionByKey[itemToMove.$2] = i;
|
_indexByKey[itemToMove.$2] = i;
|
||||||
return firstItem;
|
return firstItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateElement(K key) {
|
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));
|
final (T, K, int) item = (_items[i].$1, _items[i].$2, getPriority(_items[i].$1));
|
||||||
bool dontBubbleDown = false;
|
bool dontBubbleDown = false;
|
||||||
while (i > 0 && _items[(i-1) >> 1].$3 > item.$3) {
|
while (i > 0 && _items[(i-1) >> 1].$3 > item.$3) {
|
||||||
dontBubbleDown = true;
|
dontBubbleDown = true;
|
||||||
_items[i] = _items[(i-1) >> 1];
|
_items[i] = _items[(i-1) >> 1];
|
||||||
_positionByKey[_items[i].$2] = i;
|
_indexByKey[_items[i].$2] = i;
|
||||||
i = (i-1) >> 1;
|
i = (i-1) >> 1;
|
||||||
}
|
}
|
||||||
int leftIndex, rightIndex;
|
int leftIndex, rightIndex;
|
||||||
|
|
@ -108,28 +108,47 @@ class SearchHeap<K, T> {
|
||||||
if (leftIndex < _items.length && item.$3 > _items[leftIndex].$3) {
|
if (leftIndex < _items.length && item.$3 > _items[leftIndex].$3) {
|
||||||
if (rightIndex < _items.length && _items[leftIndex].$3 > _items[rightIndex].$3) {
|
if (rightIndex < _items.length && _items[leftIndex].$3 > _items[rightIndex].$3) {
|
||||||
_items[i] = _items[rightIndex];
|
_items[i] = _items[rightIndex];
|
||||||
_positionByKey[_items[i].$2] = i;
|
_indexByKey[_items[i].$2] = i;
|
||||||
i = rightIndex;
|
i = rightIndex;
|
||||||
} else {
|
} else {
|
||||||
_items[i] = _items[leftIndex];
|
_items[i] = _items[leftIndex];
|
||||||
_positionByKey[_items[i].$2] = i;
|
_indexByKey[_items[i].$2] = i;
|
||||||
i = leftIndex;
|
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];
|
_items[i] = _items[rightIndex];
|
||||||
_positionByKey[_items[i].$2] = i;
|
_indexByKey[_items[i].$2] = i;
|
||||||
i = rightIndex;
|
i = rightIndex;
|
||||||
} else {
|
} else {
|
||||||
dontBubbleDown = true;
|
dontBubbleDown = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_items[i] = item;
|
_items[i] = item;
|
||||||
_positionByKey[item.$2] = i;
|
_indexByKey[item.$2] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => _items.map(((T, K, int) item) => item.$1).toString();
|
String toString() => _items.map(((T, K, int) item) => item.$1).toString();
|
||||||
|
|
||||||
List<T> get debugItems => _items.map(((T, K, int) item) => item.$1).toList();
|
List<T> get debugItems => _items.map(((T, K, int) item) => item.$1).toList();
|
||||||
|
Map<K, int> 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<K, int>(key: K key, value: int index) in _indexByKey.entries) {
|
||||||
|
if (_items[index].$2 != key) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue