fix bug in trie
This commit is contained in:
parent
075cc1244f
commit
fe6e86e1a4
2 changed files with 112 additions and 24 deletions
|
|
@ -6,6 +6,21 @@ export const emptyTrie = {
|
|||
children: [],
|
||||
};
|
||||
|
||||
// invariant: the keys of a trie node should always be sorted
|
||||
export const isProperlySorted = trie => {
|
||||
for (let i=0; i<trie.children.length-1; i++) {
|
||||
if (trie.children[i] >= trie.children[i+1]) {
|
||||
return false; // not properly sorted!
|
||||
}
|
||||
}
|
||||
for (const [_, node] of trie.children) {
|
||||
if (!isProperlySorted(node)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// find maximal common prefix, and whether string A is smaller than B
|
||||
const commonPrefix = (strA, strB) => {
|
||||
let i=0
|
||||
|
|
@ -41,6 +56,14 @@ const __binarySearch = (ls, key, min, max) => {
|
|||
return __binarySearch(ls, key, middle+1, max);
|
||||
}
|
||||
|
||||
const check = trie => {
|
||||
// uncomment if you think shit is broken:
|
||||
// if (!isProperlySorted(trie)) {
|
||||
// throw new Error('not properly sorted!')
|
||||
// }
|
||||
return trie;
|
||||
}
|
||||
|
||||
// insert (key,value) into trie.
|
||||
export const insert = trie => key => value => {
|
||||
if (key.length === 0) {
|
||||
|
|
@ -54,54 +77,59 @@ export const insert = trie => key => value => {
|
|||
const [insertPos, prefix] = binarySearch(trie.children, key);
|
||||
if (insertPos === trie.children.length) {
|
||||
// insert node at end
|
||||
return {
|
||||
return check({
|
||||
value: trie.value,
|
||||
children: [
|
||||
...trie.children,
|
||||
[key, {value, children:[]}],
|
||||
],
|
||||
};
|
||||
});
|
||||
}
|
||||
if (prefix.length === 0) {
|
||||
// nothing in common...
|
||||
// insert new node into children
|
||||
return {
|
||||
return check({
|
||||
value: trie.value,
|
||||
children: trie.children.toSpliced(
|
||||
insertPos, // insert position
|
||||
0, // delete nothing
|
||||
[key, {value, children:[]}],
|
||||
),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const [haveKey, haveChildNode] = trie.children[insertPos];
|
||||
if (prefix.length === haveKey.length) {
|
||||
// recurse
|
||||
return {
|
||||
return check({
|
||||
value: trie.value,
|
||||
children: trie.children.with(
|
||||
insertPos, // position to update
|
||||
[haveKey, insert(haveChildNode)(key.slice(prefix.length))(value)],
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// otherwise, split entry:
|
||||
const havePostFix = haveKey.slice(prefix.length);
|
||||
const postFix = key.slice(prefix.length);
|
||||
return {
|
||||
return check({
|
||||
value: trie.value,
|
||||
children: trie.children.with(
|
||||
insertPos, // position to update
|
||||
[prefix, {
|
||||
children: [
|
||||
[havePostFix, haveChildNode],
|
||||
[postFix, {value, children: []}
|
||||
],
|
||||
]}],
|
||||
children: (havePostFix < postFix)
|
||||
? [
|
||||
[havePostFix, haveChildNode],
|
||||
[postFix, {value, children: []}],
|
||||
]
|
||||
: [
|
||||
[postFix, {value, children: []}],
|
||||
[havePostFix, haveChildNode],
|
||||
],
|
||||
}],
|
||||
),
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// given a prefix, return a string X such that prefix+X is a possibly larger prefix for the same entries as the original prefix.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue