Skip to content

Commit a31d5c8

Browse files
authored
Merge pull request #179 from Tr-Jono/master
Add trie implementation
2 parents e1a8f3e + 4a934ac commit a31d5c8

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

Data_Structure/src/Trees/trie.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
"""
2+
Trie implementation in Python by @Tr-Jono
3+
4+
A trie is a type of search tree that is used for storing strings.
5+
Visual representation of a trie with strings "ab", "ac", "ace", "ba", "boom":
6+
7+
[root]
8+
/ \
9+
"a" "b"
10+
/ \ / \
11+
"b" "c" "a" "o"
12+
| |
13+
"e" "o"
14+
|
15+
"m"
16+
17+
The time complexities of addition, removal and querying existence/count of a string are all O(|target string|).
18+
19+
A trie could be used in place of a string list used for searching.
20+
Time complexity of searching a string in:
21+
- a list: O(|list|)
22+
- a trie: O(|target string|)
23+
24+
This implementation of the trie relies on recursively stored _TrieNode instances.
25+
The Trie class, acting as the root, implements typical data structure methods.
26+
"""
27+
28+
29+
class _TrieNode:
30+
def __init__(self):
31+
self.words = 0
32+
self.children = {}
33+
34+
def __len__(self):
35+
return self.words + sum(len(c) for c in self.children.values())
36+
37+
def add(self, s):
38+
if not s:
39+
self.words += 1
40+
return
41+
if s[0] not in self.children:
42+
self.children[s[0]] = _TrieNode()
43+
self.children[s[0]].add(s[1:])
44+
45+
def remove(self, s):
46+
if not s:
47+
if not self.words:
48+
raise ValueError
49+
self.words -= 1
50+
return
51+
if s[0] not in self.children:
52+
raise ValueError
53+
self.children[s[0]].remove(s[1:])
54+
55+
def count(self, s):
56+
if not s:
57+
return self.words
58+
if s[0] not in self.children:
59+
return 0
60+
return self.children[s[0]].count(s[1:])
61+
62+
def get_words(self):
63+
words = [""] * self.words
64+
for c in self.children:
65+
for w in self.children[c].get_words():
66+
words.append(c + w)
67+
return words
68+
69+
70+
class Trie:
71+
def __init__(self, *words):
72+
self.children = {}
73+
for w in words:
74+
self.add(w)
75+
76+
def __contains__(self, item):
77+
return bool(self.count(item))
78+
79+
def __len__(self):
80+
return sum(len(c) for c in self.children.values())
81+
82+
def __bool__(self):
83+
return bool(len(self))
84+
85+
def __repr__(self):
86+
return "{}({})".format(self.__class__.__name__, ", ".join([repr(w) for w in self.get_words()]))
87+
88+
def add(self, s):
89+
if not s:
90+
raise ValueError("Empty strings disallowed")
91+
if s[0] not in self.children:
92+
self.children[s[0]] = _TrieNode()
93+
self.children[s[0]].add(s[1:])
94+
95+
def remove(self, s):
96+
if not s:
97+
raise ValueError("Empty strings disallowed")
98+
try:
99+
if s[0] not in self.children:
100+
raise ValueError
101+
self.children[s[0]].remove(s[1:])
102+
except ValueError:
103+
raise ValueError("{} not in trie".format(repr(s))) from None
104+
105+
def count(self, s):
106+
if s[0] not in self.children:
107+
return 0
108+
return self.children[s[0]].count(s[1:])
109+
110+
def get_words(self):
111+
words = []
112+
for c in self.children:
113+
for w in self.children[c].get_words():
114+
words.append(c + w)
115+
return words
116+
117+
118+
def main():
119+
trie = Trie("dog", "dog", "cat", "tiger")
120+
trie.add("bird")
121+
trie.remove("bird")
122+
print("repr(trie):", trie)
123+
print("len(trie):", len(trie))
124+
print("trie.count('dog'):", trie.count("dog"))
125+
print("'bird' in trie:", "bird" in trie)
126+
127+
128+
if __name__ == "__main__":
129+
main()

0 commit comments

Comments
 (0)