Skip to content

Conversation

@AngusGMorrison
Copy link
Contributor

This PR addresses #35.

It replaces the existing tombstone method of key removal with recursive deletion of unused nodes, ensuring that logarithmic time complexity for search misses is maintained even as many keys are deleted.

Additionally, it removes the valid boolean parameter from (*Trie[V]).put, which is no longer required.

t.root = t.put(t.root, key, val, 0)
}

func (t *Trie[V]) put(x *node[V], key string, val V, d int) *node[V] {
Copy link
Contributor Author

@AngusGMorrison AngusGMorrison Jan 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved put up to sit underneath Put rather than under Remove. The only functional change to this method is the removal of the valid boolean parameter.

@AngusGMorrison AngusGMorrison marked this pull request as draft January 10, 2023 19:13
@AngusGMorrison
Copy link
Contributor Author

I've switched this back to draft, as I've realized that some unnecessary keys can remain in the cases where a node should be replaced by either its left or right child. Bear with me.

Extends deletion code to delete all nodes without values or middle
children, rather than deleting only nodes whose children are all nil.
@AngusGMorrison AngusGMorrison marked this pull request as ready for review January 10, 2023 20:03
@AngusGMorrison
Copy link
Contributor Author

This is ready to review again.

x.valid = valid
var v V
x.val = v
x.valid = false
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for this case to happen? It seems like this still uses some tombstones if so (shouldn't we be aiming to completely remove valid?)

Copy link
Contributor Author

@AngusGMorrison AngusGMorrison Jan 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valid is required to distinguish between keys that have V's zero-value as their val and non-keys. We can't simply check for the presence of a value, because, for example, in a trie of ints, 0 may be either a genuine value or the zero-value of a non-key node.

To demonstrate how this case can happen, imagine a trie containing the keys "she" and "shell". When we delete "she", we must keep all the nodes, since they're still used by "shell". In this case we simply mark the "e" node as invalid (i.e. a non-key).

If the trie contained only "she", we mark the "e" node as invalid, then check whether the node has a middle child on line 174. If not, we know the node is no longer part of any active key and is safe to delete.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, sorry it’s been a while since I’ve looked at this code haha.

@zyedidia zyedidia merged commit c71d9ca into zyedidia:master Jan 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants