Skip to content

Commit 768700b

Browse files
ksangeet9apcclauss
authored andcommitted
Add delete to trie.py + tests (#1177)
* Add delete to trie.py + tests * Minor fixes + tests * Remove noqa comments + modify tests for Travis CI to detect * Minor improvement
1 parent 6fa3c0b commit 768700b

File tree

1 file changed

+68
-16
lines changed

1 file changed

+68
-16
lines changed

Diff for: data_structures/trie/trie.py

+68-16
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
"""
22
A Trie/Prefix Tree is a kind of search tree used to provide quick lookup
33
of words/patterns in a set of words. A basic Trie however has O(n^2) space complexity
4-
making it impractical in practice. It however provides O(max(search_string, length of longest word)) lookup
5-
time making it an optimal approach when space is not an issue.
6-
4+
making it impractical in practice. It however provides O(max(search_string, length of longest word))
5+
lookup time making it an optimal approach when space is not an issue.
76
"""
87

98

@@ -12,7 +11,7 @@ def __init__(self):
1211
self.nodes = dict() # Mapping from char to TrieNode
1312
self.is_leaf = False
1413

15-
def insert_many(self, words: [str]): # noqa: E999 This syntax is Python 3 only
14+
def insert_many(self, words: [str]):
1615
"""
1716
Inserts a list of words into the Trie
1817
:param words: list of string words
@@ -21,7 +20,7 @@ def insert_many(self, words: [str]): # noqa: E999 This syntax is Python 3 only
2120
for word in words:
2221
self.insert(word)
2322

24-
def insert(self, word: str): # noqa: E999 This syntax is Python 3 only
23+
def insert(self, word: str):
2524
"""
2625
Inserts a word into the Trie
2726
:param word: word to be inserted
@@ -34,7 +33,7 @@ def insert(self, word: str): # noqa: E999 This syntax is Python 3 only
3433
curr = curr.nodes[char]
3534
curr.is_leaf = True
3635

37-
def find(self, word: str) -> bool: # noqa: E999 This syntax is Python 3 only
36+
def find(self, word: str) -> bool:
3837
"""
3938
Tries to find word in a Trie
4039
:param word: word to look for
@@ -47,29 +46,82 @@ def find(self, word: str) -> bool: # noqa: E999 This syntax is Python 3 only
4746
curr = curr.nodes[char]
4847
return curr.is_leaf
4948

49+
def delete(self, word: str):
50+
"""
51+
Deletes a word in a Trie
52+
:param word: word to delete
53+
:return: None
54+
"""
5055

51-
def print_words(node: TrieNode, word: str): # noqa: E999 This syntax is Python 3 only
56+
def _delete(curr: TrieNode, word: str, index: int):
57+
if index == len(word):
58+
# If word does not exist
59+
if not curr.is_leaf:
60+
return False
61+
curr.is_leaf = False
62+
return len(curr.nodes) == 0
63+
char = word[index]
64+
char_node = curr.nodes.get(char)
65+
# If char not in current trie node
66+
if not char_node:
67+
return False
68+
# Flag to check if node can be deleted
69+
delete_curr = _delete(char_node, word, index + 1)
70+
if delete_curr:
71+
del curr.nodes[char]
72+
return len(curr.nodes) == 0
73+
return delete_curr
74+
75+
_delete(self, word, 0)
76+
77+
78+
def print_words(node: TrieNode, word: str):
5279
"""
5380
Prints all the words in a Trie
5481
:param node: root node of Trie
5582
:param word: Word variable should be empty at start
5683
:return: None
5784
"""
5885
if node.is_leaf:
59-
print(word, end=' ')
86+
print(word, end=" ")
6087

6188
for key, value in node.nodes.items():
6289
print_words(value, word + key)
6390

6491

65-
def test():
66-
words = ['banana', 'bananas', 'bandana', 'band', 'apple', 'all', 'beast']
92+
def test_trie():
93+
words = "banana bananas bandana band apple all beast".split()
6794
root = TrieNode()
6895
root.insert_many(words)
69-
# print_words(root, '')
70-
assert root.find('banana')
71-
assert not root.find('bandanas')
72-
assert not root.find('apps')
73-
assert root.find('apple')
96+
# print_words(root, "")
97+
assert all(root.find(word) for word in words)
98+
assert root.find("banana")
99+
assert not root.find("bandanas")
100+
assert not root.find("apps")
101+
assert root.find("apple")
102+
assert root.find("all")
103+
root.delete("all")
104+
assert not root.find("all")
105+
root.delete("banana")
106+
assert not root.find("banana")
107+
assert root.find("bananas")
108+
return True
109+
110+
111+
def print_results(msg: str, passes: bool) -> None:
112+
print(str(msg), "works!" if passes else "doesn't work :(")
113+
114+
115+
def pytests():
116+
assert test_trie()
117+
118+
119+
def main():
120+
"""
121+
>>> pytests()
122+
"""
123+
print_results("Testing trie functionality", test_trie())
124+
74125

75-
test()
126+
if __name__ == "__main__":
127+
main()

0 commit comments

Comments
 (0)