1
+ """
2
+ Implementation of Trie (Prefix Tree) data structure.
3
+ """
4
+
5
+ __all__ = [
6
+ 'Trie'
7
+ ]
8
+
9
+ class TrieNode :
10
+ """
11
+ Represents a node in the Trie.
12
+ """
13
+ __slots__ = ['children' , 'is_end_of_word' ]
14
+
15
+ def __init__ (self ):
16
+ """
17
+ Initializes a TrieNode.
18
+ """
19
+ self .children = {}
20
+ self .is_end_of_word = False
21
+
22
+ class Trie :
23
+ """
24
+ Represents a Trie (Prefix Tree) data structure.
25
+
26
+ Examples
27
+ ========
28
+
29
+ >>> from pydatastructs.trees.trie import Trie
30
+ >>> trie = Trie()
31
+ >>> trie.insert("apple")
32
+ >>> trie.search("apple")
33
+ True
34
+ >>> trie.search("app")
35
+ False
36
+ >>> trie.starts_with("app")
37
+ True
38
+ >>> trie.insert("app")
39
+ >>> trie.search("app")
40
+ True
41
+ >>> trie.delete("apple")
42
+ True
43
+ >>> trie.search("apple")
44
+ False
45
+ >>> trie.search("app")
46
+ True
47
+ """
48
+ __slots__ = ['root' ]
49
+
50
+ def __init__ (self ):
51
+ """
52
+ Initializes an empty Trie.
53
+ """
54
+ self .root = TrieNode ()
55
+
56
+ def insert (self , word ):
57
+ """
58
+ Inserts a word into the trie.
59
+
60
+ Parameters
61
+ ==========
62
+
63
+ word: str
64
+ The word to insert
65
+
66
+ Returns
67
+ =======
68
+
69
+ None
70
+ """
71
+ node = self .root
72
+ for char in word :
73
+ if char not in node .children :
74
+ node .children [char ] = TrieNode ()
75
+ node = node .children [char ]
76
+ node .is_end_of_word = True
77
+
78
+ def search (self , word ):
79
+ """
80
+ Returns True if the word is in the trie.
81
+
82
+ Parameters
83
+ ==========
84
+
85
+ word: str
86
+ The word to search for
87
+
88
+ Returns
89
+ =======
90
+
91
+ bool
92
+ True if the word is in the trie, False otherwise
93
+ """
94
+ node = self ._get_node (word )
95
+ return node is not None and node .is_end_of_word
96
+
97
+ def starts_with (self , prefix ):
98
+ """
99
+ Returns True if there is any word in the trie
100
+ that starts with the given prefix.
101
+
102
+ Parameters
103
+ ==========
104
+
105
+ prefix: str
106
+ The prefix to check
107
+
108
+ Returns
109
+ =======
110
+
111
+ bool
112
+ True if there is any word with the given prefix,
113
+ False otherwise
114
+ """
115
+ return self ._get_node (prefix ) is not None
116
+
117
+ def delete (self , word ):
118
+ """
119
+ Deletes a word from the trie if it exists.
120
+
121
+ Parameters
122
+ ==========
123
+
124
+ word: str
125
+ The word to delete
126
+
127
+ Returns
128
+ =======
129
+
130
+ bool
131
+ True if the word was deleted, False if it wasn't in the trie
132
+ """
133
+ def _delete_helper (node , word , depth = 0 ):
134
+ # If we've reached the end of the word
135
+ if depth == len (word ):
136
+ # If the word exists in the trie
137
+ if node .is_end_of_word :
138
+ node .is_end_of_word = False
139
+ # Return True if this node can be deleted
140
+ # (has no children and is not end of another word)
141
+ return len (node .children ) == 0
142
+ return False
143
+
144
+ char = word [depth ]
145
+ if char not in node .children :
146
+ return False
147
+
148
+ should_delete_child = _delete_helper (node .children [char ], word , depth + 1 )
149
+
150
+ # If we should delete the child
151
+ if should_delete_child :
152
+ del node .children [char ]
153
+ # Return True if this node can be deleted
154
+ # (has no children and is not end of another word)
155
+ return len (node .children ) == 0 and not node .is_end_of_word
156
+
157
+ return False
158
+
159
+ if not word :
160
+ return False
161
+
162
+ return True if _delete_helper (self .root , word ) else self .search (word )
163
+
164
+ def _get_node (self , prefix ):
165
+ """
166
+ Returns the node at the end of the prefix, or None if not found.
167
+
168
+ Parameters
169
+ ==========
170
+
171
+ prefix: str
172
+ The prefix to find
173
+
174
+ Returns
175
+ =======
176
+
177
+ TrieNode or None
178
+ The node at the end of the prefix, or None if the prefix doesn't exist
179
+ """
180
+ node = self .root
181
+ for char in prefix :
182
+ if char not in node .children :
183
+ return None
184
+ node = node .children [char ]
185
+ return node
0 commit comments