handle duplicates in insertion into trie properly (return same trie if it already has a FOUND/FOUND_WITH_CHILDREN node awith that key, or change tag of node from CHILDREN to FOUND_WITH_CHILDREN to mark it as inserted

This commit is contained in:
2024-09-08 04:41:14 +01:00
parent 88c48b0592
commit 36c9b45c1a
3 changed files with 41 additions and 15 deletions

View File

@@ -416,9 +416,24 @@ struct
* the tag/case. *) * the tag/case. *)
| FULL_INSERT_MATCH => | FULL_INSERT_MATCH =>
(* in case of a full match, (* in case of a full match,
* returned node should always be FOUND_WITH_CHILDREN, * need to turn child into FOUND_WITH_CHILDREN
* because full match means this key was inserted into the trie. *) * or FOUND case, if it not already either
FOUND_WITH_CHILDREN {keys = keys, children = children} *)
(case Vector.sub (children, insIdx) of
CHILDREN {keys = childKeys, children = childChildren} =>
let
val newTrieChild =
FOUND_WITH_CHILDREN
{keys = childKeys, children = childChildren}
val newParentChildren =
Vector.mapi
(fn (childIdx, elt) =>
if insIdx <> childIdx then elt else newTrieChild)
children
in
constructor {keys = keys, children = newParentChildren}
end
| _ => trie)
(* if insert key contains trie key, need to recurse down node *) (* if insert key contains trie key, need to recurse down node *)
| INSERT_KEY_CONTAINS_TRIE_KEY => | INSERT_KEY_CONTAINS_TRIE_KEY =>
let let
@@ -572,18 +587,16 @@ struct
in in
CHANGED newNode CHANGED newNode
end end
else else (* if the caller was from the FOUND_WITH_CHILDREN case,
(* if the caller was from the FOUND_WITH_CHILDREN case, * then, instead of deleting this node entirely,
* then, instead of deleting this node entirely, * we only delete this node's children, and mark this node
* we only delete this node's children, and mark this node * as found.
* as found. * However, in general case where this is a CHILDREN node
* However, in general case where this is a CHILDREN node * whose key was not inserted into the trie,
* whose key was not inserted into the trie, * we should fully delete this node as well. *) if isFoundWithChildren then
* we should fully delete this node as well. *) CHANGED FOUND
if isFoundWithChildren then else
CHANGED FOUND MADE_EMPTY
else
MADE_EMPTY
(* should be called when searchKeyMatch returns FULL_MATCH (* should be called when searchKeyMatch returns FULL_MATCH
*in helpRemove function *) *in helpRemove function *)

Binary file not shown.

View File

@@ -136,6 +136,17 @@ struct
print "StringSet.remove: passed remove5\n" print "StringSet.remove: passed remove5\n"
end end
fun insert1 () =
let
val trie = StringSet.empty
val _ = assertFalse (StringSet.exists ("abc", trie), "abc does not exist before it is added to trie")
val trie = StringSet.insert ("abc", trie)
val _ = assertTrue (StringSet.exists ("abc", trie), "abc exists after being addedd to trie")
in
print "StringSet.insert: passed add1\n"
end
fun run () = fun run () =
let let
val _ = testExists () val _ = testExists ()
@@ -146,6 +157,8 @@ struct
val _ = remove3 () val _ = remove3 ()
val _ = remove4 () val _ = remove4 ()
val _ = remove5 () val _ = remove5 ()
val _ = insert1 ()
in in
() ()
end end