Skip to content

Commit 81614e6

Browse files
committed
Add version history to readme; add comments; "dynamically persistent"
I described BTree as "semi-persistent", but this sounds like something that is "incomplete" compared to an ordinary "persistent" data structure, as a semicircle is merely half a circle, when in fact "semi-persistent" is something fancier than "persistent". I don't want to popularize confusing terminology, but I think that the category of "semi-persistent" data structures is a valuable one. Therefore I chose another name that doesn't have this drawback but isn't already in use. Note: my Loyc.Collections C# library contains a several other "dynamically persistent" types: ALists (including types similar to B+ trees), VLists/WLists, Set/MSet, Map/MMap. For more information, see http://core.loyc.net/collections/
1 parent c789b7e commit 81614e6

File tree

2 files changed

+33
-11
lines changed

2 files changed

+33
-11
lines changed

b+tree.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// B+ tree by David Piepgrass. License: MIT
22
import { ISortedMap, ISortedMapF } from './interfaces';
3+
34
export {
45
ISetSource, ISetSink, ISet, ISetF, ISortedSetSource, ISortedSet, ISortedSetF,
56
IMapSource, IMapSink, IMap, IMapF, ISortedMapSource, ISortedMap, ISortedMapF
@@ -207,7 +208,8 @@ export default class BTree<K=any, V=any> implements ISortedMapF<K,V>, ISortedMap
207208
this.setPairs(entries);
208209
}
209210

210-
// ES6 Map<K,V> methods ///////////////////////////////////////////////////
211+
/////////////////////////////////////////////////////////////////////////////
212+
// ES6 Map<K,V> methods /////////////////////////////////////////////////////
211213

212214
/** Gets the number of key-value pairs in the tree. */
213215
get size() { return this._size; }
@@ -313,7 +315,8 @@ export default class BTree<K=any, V=any> implements ISortedMapF<K,V>, ISortedMap
313315
return this.editRange(key, key, true, DeleteRange) !== 0;
314316
}
315317

316-
// Clone-mutators /////////////////////////////////////////////////////////
318+
/////////////////////////////////////////////////////////////////////////////
319+
// Clone-mutators ///////////////////////////////////////////////////////////
317320

318321
/** Returns a copy of the tree with the specified key set (the value is undefined). */
319322
with(key: K): BTree<K,V|undefined>;
@@ -419,7 +422,8 @@ export default class BTree<K=any, V=any> implements ISortedMapF<K,V>, ISortedMap
419422
return p;
420423
}
421424

422-
// Iterator methods ///////////////////////////////////////////////////////
425+
/////////////////////////////////////////////////////////////////////////////
426+
// Iterator methods /////////////////////////////////////////////////////////
423427

424428
/** Returns an iterator that provides items in order (ascending order if
425429
* the collection's comparator uses ascending order, as is the default.)
@@ -686,6 +690,9 @@ export default class BTree<K=any, V=any> implements ISortedMapF<K,V>, ISortedMap
686690
return BTree.finishCursorWalk(otherCursor, thisCursor, _compare, onlyOther);
687691
}
688692

693+
///////////////////////////////////////////////////////////////////////////
694+
// Helper methods for diffAgainst /////////////////////////////////////////
695+
689696
private static finishCursorWalk<K, V, R>(
690697
cursor: DiffCursor<K, V>,
691698
cursorFinished: DiffCursor<K, V>,
@@ -817,6 +824,9 @@ export default class BTree<K=any, V=any> implements ISortedMapF<K,V>, ISortedMap
817824
return depthANormalized - depthBNormalized;
818825
}
819826

827+
// End of helper methods for diffAgainst //////////////////////////////////
828+
///////////////////////////////////////////////////////////////////////////
829+
820830
/** Returns a new iterator for iterating the keys of each pair in ascending order.
821831
* @param firstKey: Minimum key to include in the output. */
822832
keys(firstKey?: K): IterableIterator<K> {
@@ -839,7 +849,8 @@ export default class BTree<K=any, V=any> implements ISortedMapF<K,V>, ISortedMap
839849
});
840850
}
841851

842-
// Additional methods /////////////////////////////////////////////////////
852+
/////////////////////////////////////////////////////////////////////////////
853+
// Additional methods ///////////////////////////////////////////////////////
843854

844855
/** Returns the maximum number of children/values before nodes will split. */
845856
get maxNodeSize() {
@@ -1164,6 +1175,7 @@ class BNode<K,V> {
11641175
this.isShared = undefined;
11651176
}
11661177

1178+
///////////////////////////////////////////////////////////////////////////
11671179
// Shared methods /////////////////////////////////////////////////////////
11681180

11691181
maxKey() {
@@ -1240,6 +1252,7 @@ class BNode<K,V> {
12401252
return c === 0 ? i : i ^ failXor;*/
12411253
}
12421254

1255+
/////////////////////////////////////////////////////////////////////////////
12431256
// Leaf Node: misc //////////////////////////////////////////////////////////
12441257

12451258
minKey() {
@@ -1273,6 +1286,7 @@ class BNode<K,V> {
12731286
return kL;
12741287
}
12751288

1289+
/////////////////////////////////////////////////////////////////////////////
12761290
// Leaf Node: set & node splitting //////////////////////////////////////////
12771291

12781292
set(key: K, value: V, overwrite: boolean|undefined, tree: BTree<K,V>): boolean|BNode<K,V> {
@@ -1365,6 +1379,7 @@ class BNode<K,V> {
13651379
return new BNode<K,V>(keys, values);
13661380
}
13671381

1382+
/////////////////////////////////////////////////////////////////////////////
13681383
// Leaf Node: scanning & deletions //////////////////////////////////////////
13691384

13701385
forRange<R>(low: K, high: K, includeHigh: boolean|undefined, editMode: boolean, tree: BTree<K,V>, count: number,
@@ -1491,6 +1506,7 @@ class BNodeInternal<K,V> extends BNode<K,V> {
14911506
return size;
14921507
}
14931508

1509+
/////////////////////////////////////////////////////////////////////////////
14941510
// Internal Node: set & node splitting //////////////////////////////////////
14951511

14961512
set(key: K, value: V, overwrite: boolean|undefined, tree: BTree<K,V>): boolean|BNodeInternal<K,V> {
@@ -1566,6 +1582,7 @@ class BNodeInternal<K,V> extends BNode<K,V> {
15661582
this.children.unshift((lhs as BNodeInternal<K,V>).children.pop()!);
15671583
}
15681584

1585+
/////////////////////////////////////////////////////////////////////////////
15691586
// Internal Node: scanning & deletions //////////////////////////////////////
15701587

15711588
// Note: `count` is the next value of the third argument to `onFound`.

readme.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ Features
2424
- Supports O(1) fast cloning with subtree sharing. This works by marking the
2525
root node as "shared between instances". This makes the tree read-only
2626
with copy-on-edit behavior; both copies of the tree remain mutable.
27-
I call this category of data structure "semi-persistent" because AFAIK no
28-
one else has given it a name; it walks the line between mutating and
29-
[persistent](https://en.wikipedia.org/wiki/Persistent_data_structure).
27+
I call this category of data structure "dynamically persistent" because
28+
AFAIK no one else has given it a name; it walks the line between mutating
29+
and [persistent](https://en.wikipedia.org/wiki/Persistent_data_structure).
3030
- Includes persistent methods such as `with` and `without`, which return a
3131
modified tree without changing the original (in O(log(size)) time).
3232
- When a node fills up, items are shifted to siblings when possible to
@@ -36,7 +36,7 @@ Features
3636
with all keys in a given node.
3737
- Includes neat stuff such as `Range` methods for batch operations
3838
- Throws an exception if you try to use `NaN` as a key, but infinity is allowed.
39-
- No dependencies. 16K minified.
39+
- No dependencies. 18K minified.
4040
- Includes a lattice of interfaces for TypeScript users (see below)
4141
- Supports diffing computation between two trees that is highly optimized for the case
4242
in which a majority of nodes are shared (such as when persistent methods are used).
@@ -58,7 +58,7 @@ Features
5858
- Get largest key/pair that is lower than `k`: `t.nextLowerKey(k)`, `t.nextLowerPair(k)`
5959
- Freeze to prevent modifications: `t.freeze()` (you can also `t.unfreeze()`)
6060
- Fast clone: `t.clone()`
61-
- Compute a diff between two trees: `t.diffAgainst(otherTree, ...)`
61+
- Compute a diff between two trees (quickly skipping shared subtrees): `t.diffAgainst(otherTree, ...)`
6262
- For more information, **see [full documentation](https://github.com/qwertie/btree-typescript/blob/master/b%2Btree.ts) in the source code.**
6363

6464
**Note:** Confusingly, the ES6 `Map.forEach(c)` method calls `c(value,key)` instead of `c(key,value)`, in contrast to other methods such as `set()` and `entries()` which put the key first. I can only assume that they reversed the order on the hypothesis that users would usually want to examine values and ignore keys. BTree's `forEach()` therefore works the same way, but there is a second method `.forEachPair((key,value)=>{...})` which sends you the key first and the value second; this method is slightly faster because it is the "native" for-each method for this class.
@@ -375,6 +375,12 @@ Benchmarks (in milliseconds for integer keys/values)
375375
Version history
376376
---------------
377377

378+
### v1.5.0 ###
379+
380+
- Added `BTree.diffAgainst` method (PR #16)
381+
- Added `simpleComparator` function (PR #15)
382+
- Improved `defaultComparator` (PR #15) to support edge cases better. Most notably, heterogenous key types will no longer cause trouble such as failure to find keys that are, in fact, present in the tree. `BTree` is slightly slower using the new default comparator, but the benchmarks above have not been refreshed. For maximum performance, use `simpleComparator` or a custom comparator as the second constructor parameter. The simplest possible comparator is `(a, b) => a - b`, which works for finite numbers only.
383+
378384
### v1.4.0 ###
379385

380386
- Now built as CommonJS module instead of UMD module, for better compatibility with webpack. No semantic change.
@@ -419,7 +425,6 @@ Version history
419425

420426
♥ This package was made to help people [learn TypeScript & React](http://typescript-react-primer.loyc.net/).
421427

422-
Are you a C# developer? You might like the similar data structures I made for C#:
423-
BDictionary, BList, etc. See http://core.loyc.net/collections/
428+
Are you a C# developer? You might like the similar data structures I made for C# ([BDictionary, BList, etc.](core.loyc.net/collections/alists-part2)), and other [dynamically persistent collection types](http://core.loyc.net/collections/).
424429

425430
You might think that the package name "sorted btree" is overly redundant, but I _did_ make a data structure similar to B+ Tree that is _not_ sorted. I called it the [A-List](http://core.loyc.net/collections/alists-part1) (C#). But yeah, the names `btree` and `bplustree` were already taken, so what was I supposed to do, right?

0 commit comments

Comments
 (0)