Skip to content

Commit fa7694c

Browse files
committed
PR feedback
1 parent e9d55af commit fa7694c

File tree

4 files changed

+185
-58
lines changed

4 files changed

+185
-58
lines changed

b+tree.d.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -327,19 +327,30 @@ export default class BTree<K = any, V = any> implements ISortedMapF<K, V>, ISort
327327
*/
328328
setIfNotPresent(key: K, value: V): boolean;
329329
/** Returns the next pair whose key is larger than the specified key (or undefined if there is none).
330-
* If key === undefined, this function returns the lowest pair.
330+
* If key === undefined, this function returns the lowest pair.
331+
* @param key The key to search for.
332+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
333+
* avoid creating a new array on every iteration.
331334
*/
332-
nextHigherPair(key: K | undefined): [K, V] | undefined;
335+
nextHigherPair(key: K | undefined, reusedArray?: [K, V]): [K, V] | undefined;
333336
/** Returns the next key larger than the specified key (or undefined if there is none) */
334337
nextHigherKey(key: K | undefined): K | undefined;
335338
/** Returns the next pair whose key is smaller than the specified key (or undefined if there is none).
336339
* If key === undefined, this function returns the highest pair.
340+
* @param key The key to search for.
341+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
342+
* avoid creating a new array on every iteration.
337343
*/
338-
nextLowerPair(key: K | undefined): [K, V] | undefined;
344+
nextLowerPair(key: K | undefined, reusedArray?: [K, V]): [K, V] | undefined;
339345
/** Returns the next key smaller than the specified key (or undefined if there is none) */
340346
nextLowerKey(key: K | undefined): K | undefined;
341-
/** Returns the key-value pair associated with the supplied key if it exists and the next lower pair otherwise (or undefined if there is none) */
342-
getOrNextLower(key: K): [K, V] | undefined;
347+
/** Returns the key-value pair associated with the supplied key if it exists
348+
* and the next lower pair otherwise (or undefined if there is none)
349+
* @param key The key to search for.
350+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
351+
* avoid creating a new array on every iteration.
352+
* */
353+
getPairOrNextLower(key: K, reusedArray?: [K, V]): [K, V] | undefined;
343354
/** Edits the value associated with a key in the tree, if it already exists.
344355
* @returns true if the key existed, false if not.
345356
*/

b+tree.js

Lines changed: 80 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -821,40 +821,49 @@ var BTree = /** @class */ (function () {
821821
return this.set(key, value, false);
822822
};
823823
/** Returns the next pair whose key is larger than the specified key (or undefined if there is none).
824-
* If key === undefined, this function returns the lowest pair.
824+
* If key === undefined, this function returns the lowest pair.
825+
* @param key The key to search for.
826+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
827+
* avoid creating a new array on every iteration.
825828
*/
826-
BTree.prototype.nextHigherPair = function (key) {
827-
var it = this.entries(key, ReusedArray);
828-
var r = it.next();
829-
if (!r.done && key !== undefined && this._compare(r.value[0], key) <= 0)
830-
r = it.next();
831-
return r.value;
829+
BTree.prototype.nextHigherPair = function (key, reusedArray) {
830+
var pair = reusedArray !== null && reusedArray !== void 0 ? reusedArray : [];
831+
if (key === undefined) {
832+
return this._root.minPair(pair);
833+
}
834+
return this._root.getPairOrNextHigher(key, this, false, pair);
832835
};
833836
/** Returns the next key larger than the specified key (or undefined if there is none) */
834837
BTree.prototype.nextHigherKey = function (key) {
835-
var p = this.nextHigherPair(key);
838+
var p = this.nextHigherPair(key, ReusedArray);
836839
return p ? p[0] : p;
837840
};
838841
/** Returns the next pair whose key is smaller than the specified key (or undefined if there is none).
839842
* If key === undefined, this function returns the highest pair.
843+
* @param key The key to search for.
844+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
845+
* avoid creating a new array on every iteration.
840846
*/
841-
BTree.prototype.nextLowerPair = function (key) {
847+
BTree.prototype.nextLowerPair = function (key, reusedArray) {
848+
var pair = reusedArray !== null && reusedArray !== void 0 ? reusedArray : [];
842849
if (key === undefined) {
843-
var maxKey = this.maxKey();
844-
if (maxKey === undefined)
845-
return undefined;
846-
return [maxKey, this.get(maxKey)];
850+
return this._root.maxPair(pair);
847851
}
848-
return this._root.getOrNextLower(key, this, false);
852+
return this._root.getPairOrNextLower(key, this, false, pair);
849853
};
850854
/** Returns the next key smaller than the specified key (or undefined if there is none) */
851855
BTree.prototype.nextLowerKey = function (key) {
852-
var p = this.nextLowerPair(key);
856+
var p = this.nextLowerPair(key, ReusedArray);
853857
return p ? p[0] : p;
854858
};
855-
/** Returns the key-value pair associated with the supplied key if it exists and the next lower pair otherwise (or undefined if there is none) */
856-
BTree.prototype.getOrNextLower = function (key) {
857-
return this._root.getOrNextLower(key, this, true);
859+
/** Returns the key-value pair associated with the supplied key if it exists
860+
* and the next lower pair otherwise (or undefined if there is none)
861+
* @param key The key to search for.
862+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
863+
* avoid creating a new array on every iteration.
864+
* */
865+
BTree.prototype.getPairOrNextLower = function (key, reusedArray) {
866+
return this._root.getPairOrNextLower(key, this, true, reusedArray !== null && reusedArray !== void 0 ? reusedArray : []);
858867
};
859868
/** Edits the value associated with a key in the tree, if it already exists.
860869
* @returns true if the key existed, false if not.
@@ -1147,6 +1156,21 @@ var BNode = /** @class */ (function () {
11471156
BNode.prototype.minKey = function () {
11481157
return this.keys[0];
11491158
};
1159+
BNode.prototype.minPair = function (reusedArray) {
1160+
if (this.keys.length === 0)
1161+
return undefined;
1162+
reusedArray[0] = this.keys[0];
1163+
reusedArray[1] = this.values[0];
1164+
return reusedArray;
1165+
};
1166+
BNode.prototype.maxPair = function (reusedArray) {
1167+
if (this.keys.length === 0)
1168+
return undefined;
1169+
var lastIndex = this.keys.length - 1;
1170+
reusedArray[0] = this.keys[lastIndex];
1171+
reusedArray[1] = this.values[lastIndex];
1172+
return reusedArray;
1173+
};
11501174
BNode.prototype.clone = function () {
11511175
var v = this.values;
11521176
return new BNode(this.keys.slice(0), v === undefVals ? v : v.slice(0));
@@ -1158,10 +1182,26 @@ var BNode = /** @class */ (function () {
11581182
var i = this.indexOf(key, -1, tree._compare);
11591183
return i < 0 ? defaultValue : this.values[i];
11601184
};
1161-
BNode.prototype.getOrNextLower = function (key, tree, inclusive) {
1185+
BNode.prototype.getPairOrNextLower = function (key, tree, inclusive, reusedArray) {
11621186
var i = this.indexOf(key, -1, tree._compare);
11631187
var indexOrLower = i < 0 ? (i ^ -1) - 1 : (inclusive ? i : i - 1);
1164-
return indexOrLower >= 0 ? [this.keys[indexOrLower], this.values[indexOrLower]] : undefined;
1188+
if (indexOrLower >= 0) {
1189+
reusedArray[0] = this.keys[indexOrLower];
1190+
reusedArray[1] = this.values[indexOrLower];
1191+
return reusedArray;
1192+
}
1193+
return undefined;
1194+
};
1195+
BNode.prototype.getPairOrNextHigher = function (key, tree, inclusive, reusedArray) {
1196+
var i = this.indexOf(key, -1, tree._compare);
1197+
var indexOrLower = i < 0 ? i ^ -1 : (inclusive ? i : i + 1);
1198+
var keys = this.keys;
1199+
if (indexOrLower < keys.length) {
1200+
reusedArray[0] = keys[indexOrLower];
1201+
reusedArray[1] = this.values[indexOrLower];
1202+
return reusedArray;
1203+
}
1204+
return undefined;
11651205
};
11661206
BNode.prototype.checkValid = function (depth, tree, baseIndex) {
11671207
var kL = this.keys.length, vL = this.values.length;
@@ -1357,19 +1397,33 @@ var BNodeInternal = /** @class */ (function (_super) {
13571397
BNodeInternal.prototype.minKey = function () {
13581398
return this.children[0].minKey();
13591399
};
1400+
BNodeInternal.prototype.minPair = function (reusedArray) {
1401+
return this.children[0].minPair(reusedArray);
1402+
};
1403+
BNodeInternal.prototype.maxPair = function (reusedArray) {
1404+
return this.children[this.children.length - 1].maxPair(reusedArray);
1405+
};
13601406
BNodeInternal.prototype.get = function (key, defaultValue, tree) {
13611407
var i = this.indexOf(key, 0, tree._compare), children = this.children;
13621408
return i < children.length ? children[i].get(key, defaultValue, tree) : undefined;
13631409
};
1364-
BNodeInternal.prototype.getOrNextLower = function (key, tree, inclusive) {
1410+
BNodeInternal.prototype.getPairOrNextLower = function (key, tree, inclusive, reusedArray) {
13651411
var i = this.indexOf(key, 0, tree._compare), children = this.children;
1366-
if (i > children.length)
1412+
if (i >= children.length)
13671413
return undefined;
1368-
var result = children[i].getOrNextLower(key, tree, inclusive);
1414+
var result = children[i].getPairOrNextLower(key, tree, inclusive, reusedArray);
13691415
if (result === undefined && i > 0) {
1370-
var child = children[i - 1];
1371-
var maxKey = child.maxKey();
1372-
return [maxKey, child.get(maxKey, undefined, tree)];
1416+
return children[i - 1].maxPair(reusedArray);
1417+
}
1418+
return result;
1419+
};
1420+
BNodeInternal.prototype.getPairOrNextHigher = function (key, tree, inclusive, reusedArray) {
1421+
var i = this.indexOf(key, 0, tree._compare), children = this.children, length = children.length;
1422+
if (i >= length)
1423+
return undefined;
1424+
var result = children[i].getPairOrNextHigher(key, tree, inclusive, reusedArray);
1425+
if (result === undefined && i < length - 1) {
1426+
return children[i + 1].minPair(reusedArray);
13731427
}
13741428
return result;
13751429
};

b+tree.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ function testBTree(maxNodeSize: number)
430430
pairs.push([i, value]);
431431
}
432432
test(`nextLowerPair/nextHigherPair for tree of size ${size}`, () => {
433+
expect(tree.nextHigherPair(undefined)).toEqual([tree.minKey()!, tree.get(tree.minKey()!)]);
433434
for (let i = 0; i < size; i++) {
434435
if (i > 0) {
435436
expect(tree.nextLowerPair(i)).toEqual(pairs[i - 1]);
@@ -438,6 +439,7 @@ function testBTree(maxNodeSize: number)
438439
expect(tree.nextHigherPair(i)).toEqual(pairs[i + 1]);
439440
}
440441
}
442+
expect(tree.nextLowerPair(undefined)).toEqual([tree.maxKey()!, tree.get(tree.maxKey()!)]);
441443
})
442444
}
443445

b+tree.ts

Lines changed: 87 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -925,44 +925,53 @@ export default class BTree<K=any, V=any> implements ISortedMapF<K,V>, ISortedMap
925925
}
926926

927927
/** Returns the next pair whose key is larger than the specified key (or undefined if there is none).
928-
* If key === undefined, this function returns the lowest pair.
928+
* If key === undefined, this function returns the lowest pair.
929+
* @param key The key to search for.
930+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
931+
* avoid creating a new array on every iteration.
929932
*/
930-
nextHigherPair(key: K|undefined): [K,V]|undefined {
931-
var it = this.entries(key, ReusedArray);
932-
var r = it.next();
933-
if (!r.done && key !== undefined && this._compare(r.value[0], key) <= 0)
934-
r = it.next();
935-
return r.value;
933+
nextHigherPair(key: K|undefined, reusedArray?: [K,V]): [K,V]|undefined {
934+
const pair = reusedArray ?? ([] as unknown as [K,V]);
935+
if (key === undefined) {
936+
return this._root.minPair(pair);
937+
}
938+
return this._root.getPairOrNextHigher(key, this, false, pair);
936939
}
937940

938941
/** Returns the next key larger than the specified key (or undefined if there is none) */
939942
nextHigherKey(key: K|undefined): K|undefined {
940-
var p = this.nextHigherPair(key);
943+
var p = this.nextHigherPair(key, ReusedArray as [K,V]);
941944
return p ? p[0] : p;
942945
}
943946

944947
/** Returns the next pair whose key is smaller than the specified key (or undefined if there is none).
945948
* If key === undefined, this function returns the highest pair.
949+
* @param key The key to search for.
950+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
951+
* avoid creating a new array on every iteration.
946952
*/
947-
nextLowerPair(key: K|undefined): [K,V]|undefined {
953+
nextLowerPair(key: K|undefined, reusedArray?: [K,V]): [K,V]|undefined {
954+
const pair = reusedArray ?? ([] as unknown as [K,V]);
948955
if (key === undefined) {
949-
const maxKey = this.maxKey();
950-
if (maxKey === undefined)
951-
return undefined;
952-
return [maxKey, this.get(maxKey) as V];
956+
return this._root.maxPair(pair);
953957
}
954-
return this._root.getOrNextLower(key, this, false);
958+
return this._root.getPairOrNextLower(key, this, false, pair);
955959
}
956960

957961
/** Returns the next key smaller than the specified key (or undefined if there is none) */
958962
nextLowerKey(key: K|undefined): K|undefined {
959-
var p = this.nextLowerPair(key);
963+
var p = this.nextLowerPair(key, ReusedArray as [K,V]);
960964
return p ? p[0] : p;
961965
}
962966

963-
/** Returns the key-value pair associated with the supplied key if it exists and the next lower pair otherwise (or undefined if there is none) */
964-
getOrNextLower(key: K): [K,V]|undefined {
965-
return this._root.getOrNextLower(key, this, true);
967+
/** Returns the key-value pair associated with the supplied key if it exists
968+
* and the next lower pair otherwise (or undefined if there is none)
969+
* @param key The key to search for.
970+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
971+
* avoid creating a new array on every iteration.
972+
* */
973+
getPairOrNextLower(key: K, reusedArray?: [K,V]): [K,V]|undefined {
974+
return this._root.getPairOrNextLower(key, this, true, reusedArray ?? ([] as unknown as [K,V]));
966975
}
967976

968977
/** Edits the value associated with a key in the tree, if it already exists.
@@ -1265,10 +1274,27 @@ class BNode<K,V> {
12651274
/////////////////////////////////////////////////////////////////////////////
12661275
// Leaf Node: misc //////////////////////////////////////////////////////////
12671276

1268-
minKey() {
1277+
minKey(): K | undefined {
12691278
return this.keys[0];
12701279
}
12711280

1281+
minPair(reusedArray: [K,V]): [K,V] | undefined {
1282+
if (this.keys.length === 0)
1283+
return undefined;
1284+
reusedArray[0] = this.keys[0];
1285+
reusedArray[1] = this.values[0];
1286+
return reusedArray;
1287+
}
1288+
1289+
maxPair(reusedArray: [K,V]): [K,V] | undefined {
1290+
if (this.keys.length === 0)
1291+
return undefined;
1292+
const lastIndex = this.keys.length - 1;
1293+
reusedArray[0] = this.keys[lastIndex];
1294+
reusedArray[1] = this.values[lastIndex];
1295+
return reusedArray;
1296+
}
1297+
12721298
clone(): BNode<K,V> {
12731299
var v = this.values;
12741300
return new BNode<K,V>(this.keys.slice(0), v === undefVals ? v : v.slice(0));
@@ -1283,10 +1309,27 @@ class BNode<K,V> {
12831309
return i < 0 ? defaultValue : this.values[i];
12841310
}
12851311

1286-
getOrNextLower(key: K, tree: BTree<K,V>, inclusive: boolean): [K,V]|undefined {
1312+
getPairOrNextLower(key: K, tree: BTree<K,V>, inclusive: boolean, reusedArray: [K,V]): [K,V]|undefined {
12871313
var i = this.indexOf(key, -1, tree._compare);
12881314
const indexOrLower = i < 0 ? (i ^ -1) - 1 : (inclusive ? i : i - 1);
1289-
return indexOrLower >= 0 ? [this.keys[indexOrLower], this.values[indexOrLower]] : undefined;
1315+
if (indexOrLower >= 0) {
1316+
reusedArray[0] = this.keys[indexOrLower];
1317+
reusedArray[1] = this.values[indexOrLower];
1318+
return reusedArray;
1319+
}
1320+
return undefined;
1321+
}
1322+
1323+
getPairOrNextHigher(key: K, tree: BTree<K,V>, inclusive: boolean, reusedArray: [K,V]): [K,V]|undefined {
1324+
var i = this.indexOf(key, -1, tree._compare);
1325+
const indexOrLower = i < 0 ? i ^ -1 : (inclusive ? i : i + 1);
1326+
const keys = this.keys;
1327+
if (indexOrLower < keys.length) {
1328+
reusedArray[0] = keys[indexOrLower];
1329+
reusedArray[1] = this.values[indexOrLower];
1330+
return reusedArray;
1331+
}
1332+
return undefined;
12901333
}
12911334

12921335
checkValid(depth: number, tree: BTree<K,V>, baseIndex: number): number {
@@ -1494,20 +1537,37 @@ class BNodeInternal<K,V> extends BNode<K,V> {
14941537
return this.children[0].minKey();
14951538
}
14961539

1540+
minPair(reusedArray: [K,V]): [K,V] | undefined {
1541+
return this.children[0].minPair(reusedArray);
1542+
}
1543+
1544+
maxPair(reusedArray: [K,V]): [K,V] | undefined {
1545+
return this.children[this.children.length - 1].maxPair(reusedArray);
1546+
}
1547+
14971548
get(key: K, defaultValue: V|undefined, tree: BTree<K,V>): V|undefined {
14981549
var i = this.indexOf(key, 0, tree._compare), children = this.children;
14991550
return i < children.length ? children[i].get(key, defaultValue, tree) : undefined;
15001551
}
15011552

1502-
getOrNextLower(key: K, tree: BTree<K,V>, inclusive: boolean): [K,V]|undefined {
1553+
getPairOrNextLower(key: K, tree: BTree<K,V>, inclusive: boolean, reusedArray: [K,V]): [K,V]|undefined {
15031554
var i = this.indexOf(key, 0, tree._compare), children = this.children;
1504-
if (i > children.length)
1555+
if (i >= children.length)
15051556
return undefined;
1506-
const result = children[i].getOrNextLower(key, tree, inclusive);
1557+
const result = children[i].getPairOrNextLower(key, tree, inclusive, reusedArray);
15071558
if (result === undefined && i > 0) {
1508-
const child = children[i - 1];
1509-
const maxKey = child.maxKey();
1510-
return [maxKey, child.get(maxKey, undefined, tree) as V];
1559+
return children[i - 1].maxPair(reusedArray);
1560+
}
1561+
return result;
1562+
}
1563+
1564+
getPairOrNextHigher(key: K, tree: BTree<K,V>, inclusive: boolean, reusedArray: [K,V]): [K,V]|undefined {
1565+
var i = this.indexOf(key, 0, tree._compare), children = this.children, length = children.length;
1566+
if (i >= length)
1567+
return undefined;
1568+
const result = children[i].getPairOrNextHigher(key, tree, inclusive, reusedArray);
1569+
if (result === undefined && i < length - 1) {
1570+
return children[i + 1].minPair(reusedArray);
15111571
}
15121572
return result;
15131573
}

0 commit comments

Comments
 (0)