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:
@@ -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.
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user