faster SortedList._search

This commit is contained in:
Jörg Breitbart
2023-08-10 00:12:00 +02:00
parent a84a95055d
commit 2b79b7b29f
+24 -21
View File
@@ -28,7 +28,7 @@ export class SortedList<T> {
this._array.push(value); this._array.push(value);
return; return;
} }
i = this._search(this._getKey(value), 0, this._array.length - 1); i = this._search(this._getKey(value));
this._array.splice(i, 0, value); this._array.splice(i, 0, value);
} }
@@ -40,7 +40,7 @@ export class SortedList<T> {
if (key === undefined) { if (key === undefined) {
return false; return false;
} }
i = this._search(key, 0, this._array.length - 1); i = this._search(key);
if (i === -1) { if (i === -1) {
return false; return false;
} }
@@ -60,7 +60,7 @@ export class SortedList<T> {
if (this._array.length === 0) { if (this._array.length === 0) {
return; return;
} }
i = this._search(key, 0, this._array.length - 1); i = this._search(key);
if (i < 0 || i >= this._array.length) { if (i < 0 || i >= this._array.length) {
return; return;
} }
@@ -76,7 +76,7 @@ export class SortedList<T> {
if (this._array.length === 0) { if (this._array.length === 0) {
return; return;
} }
i = this._search(key, 0, this._array.length - 1); i = this._search(key);
if (i < 0 || i >= this._array.length) { if (i < 0 || i >= this._array.length) {
return; return;
} }
@@ -92,23 +92,26 @@ export class SortedList<T> {
return this._array.values(); return this._array.values();
} }
private _search(key: number, min: number, max: number): number { private _search(key: number): number {
if (max < min) { let min = 0;
return min; let max = this._array.length - 1;
while (max >= min) {
let mid = (min + max) >> 1;
const midKey = this._getKey(this._array[mid]);
if (midKey > key) {
max = mid - 1;
} else if (midKey < key) {
min = mid + 1;
} else {
// key in list, walk to lowest duplicate
while (mid > 0 && this._getKey(this._array[mid - 1]) === key) {
mid--;
}
return mid;
}
} }
let mid = Math.floor((min + max) / 2); // key not in list
const midKey = this._getKey(this._array[mid]); // still return closest min (also used as insert position)
if (midKey > key) { return min;
return this._search(key, min, mid - 1);
}
if (midKey < key) {
return this._search(key, mid + 1, max);
}
// Value found! Since keys can be duplicates, move the result index back to the lowest index
// that matches the key.
while (mid > 0 && this._getKey(this._array[mid - 1]) === key) {
mid--;
}
return mid;
} }
} }