1
1
package com .thealgorithms .datastructures .trees ;
2
2
3
+ import java .util .HashMap ;
4
+
5
+ /**
6
+ * Represents a Trie Node that stores a character and pointers to its children.
7
+ * Each node has a hashmap which can point to all possible characters.
8
+ * Each node also has a boolean value to indicate if it is the end of a word.
9
+ */
10
+ class TrieNode {
11
+ char value ;
12
+ HashMap <Character , TrieNode > child ;
13
+ boolean end ;
14
+
15
+ /**
16
+ * Constructor to initialize a TrieNode with an empty hashmap
17
+ * and set end to false.
18
+ */
19
+ TrieNode (char value ) {
20
+ this .value = value ;
21
+ this .child = new HashMap <>();
22
+ this .end = false ;
23
+ }
24
+ }
25
+
3
26
/**
4
27
* Trie Data structure implementation without any libraries.
5
28
* <p>
14
37
* possible character.
15
38
*
16
39
* @author <a href="https://github.com/dheeraj92">Dheeraj Kumar Barnwal</a>
40
+ * @author <a href="https://github.com/sailok">Sailok Chinta</a>
17
41
*/
18
- public class TrieImp {
19
42
20
- /**
21
- * Represents a Trie Node that stores a character and pointers to its children.
22
- * Each node has an array of 26 children (one for each letter from 'a' to 'z').
23
- */
24
- public class TrieNode {
25
-
26
- TrieNode [] child ;
27
- boolean end ;
28
-
29
- /**
30
- * Constructor to initialize a TrieNode with an empty child array
31
- * and set end to false.
32
- */
33
- public TrieNode () {
34
- child = new TrieNode [26 ];
35
- end = false ;
36
- }
37
- }
43
+ public class Trie {
44
+ private static final char ROOT_NODE_VALUE = '*' ;
38
45
39
46
private final TrieNode root ;
40
47
41
48
/**
42
49
* Constructor to initialize the Trie.
43
50
* The root node is created but doesn't represent any character.
44
51
*/
45
- public TrieImp () {
46
- root = new TrieNode ();
52
+ public Trie () {
53
+ root = new TrieNode (ROOT_NODE_VALUE );
47
54
}
48
55
49
56
/**
@@ -57,13 +64,15 @@ public TrieImp() {
57
64
public void insert (String word ) {
58
65
TrieNode currentNode = root ;
59
66
for (int i = 0 ; i < word .length (); i ++) {
60
- TrieNode node = currentNode .child [word .charAt (i ) - 'a' ];
67
+ TrieNode node = currentNode .child .getOrDefault (word .charAt (i ), null );
68
+
61
69
if (node == null ) {
62
- node = new TrieNode ();
63
- currentNode .child [ word .charAt (i ) - 'a' ] = node ;
70
+ node = new TrieNode (word . charAt ( i ) );
71
+ currentNode .child . put ( word .charAt (i ), node ) ;
64
72
}
65
73
currentNode = node ;
66
74
}
75
+
67
76
currentNode .end = true ;
68
77
}
69
78
@@ -80,13 +89,14 @@ public void insert(String word) {
80
89
public boolean search (String word ) {
81
90
TrieNode currentNode = root ;
82
91
for (int i = 0 ; i < word .length (); i ++) {
83
- char ch = word .charAt (i );
84
- TrieNode node = currentNode . child [ ch - 'a' ];
92
+ TrieNode node = currentNode . child . getOrDefault ( word .charAt (i ), null );
93
+
85
94
if (node == null ) {
86
95
return false ;
87
96
}
88
97
currentNode = node ;
89
98
}
99
+
90
100
return currentNode .end ;
91
101
}
92
102
@@ -104,40 +114,89 @@ public boolean search(String word) {
104
114
public boolean delete (String word ) {
105
115
TrieNode currentNode = root ;
106
116
for (int i = 0 ; i < word .length (); i ++) {
107
- char ch = word .charAt (i );
108
- TrieNode node = currentNode .child [ch - 'a' ];
117
+ TrieNode node = currentNode .child .getOrDefault (word .charAt (i ), null );
109
118
if (node == null ) {
110
119
return false ;
111
120
}
121
+
112
122
currentNode = node ;
113
123
}
124
+
114
125
if (currentNode .end ) {
115
126
currentNode .end = false ;
116
127
return true ;
117
128
}
129
+
118
130
return false ;
119
131
}
120
132
121
133
/**
122
- * Helper method to print a string to the console.
134
+ * Counts the number of words in the trie
135
+ *<p>
136
+ * The method traverses the Trie and counts the number of words.
123
137
*
124
- * @param print The string to be printed.
138
+ * @return count of words
125
139
*/
126
- public static void sop (String print ) {
127
- System .out .println (print );
140
+ public int countWords () {
141
+ return countWords (root );
142
+ }
143
+
144
+ private int countWords (TrieNode node ) {
145
+ if (node == null ) {
146
+ return 0 ;
147
+ }
148
+
149
+ int count = 0 ;
150
+ if (node .end ) {
151
+ count ++;
152
+ }
153
+
154
+ for (TrieNode child : node .child .values ()) {
155
+ count += countWords (child );
156
+ }
157
+
158
+ return count ;
128
159
}
129
160
130
161
/**
131
- * Validates if a given word contains only lowercase alphabetic characters
132
- * (a-z).
133
- * <p>
134
- * The method uses a regular expression to check if the word matches the pattern
135
- * of only lowercase letters.
162
+ * Check if the prefix exists in the trie
136
163
*
137
- * @param word The word to be validated.
138
- * @return true if the word is valid (only a-z), false otherwise.
164
+ * @param prefix the prefix to be checked in the Trie
165
+ * @return true / false depending on the prefix if exists in the Trie
139
166
*/
140
- public static boolean isValid (String word ) {
141
- return word .matches ("^[a-z]+$" );
167
+ public boolean startsWithPrefix (String prefix ) {
168
+ TrieNode currentNode = root ;
169
+
170
+ for (int i = 0 ; i < prefix .length (); i ++) {
171
+ TrieNode node = currentNode .child .getOrDefault (prefix .charAt (i ), null );
172
+ if (node == null ) {
173
+ return false ;
174
+ }
175
+
176
+ currentNode = node ;
177
+ }
178
+
179
+ return true ;
180
+ }
181
+
182
+ /**
183
+ * Count the number of words starting with the given prefix in the trie
184
+ *
185
+ * @param prefix the prefix to be checked in the Trie
186
+ * @return count of words
187
+ */
188
+ public int countWordsWithPrefix (String prefix ) {
189
+ TrieNode currentNode = root ;
190
+
191
+ for (int i = 0 ; i < prefix .length (); i ++) {
192
+ TrieNode node = currentNode .child .getOrDefault (prefix .charAt (i ), null );
193
+ if (node == null ) {
194
+ return 0 ;
195
+ }
196
+
197
+ currentNode = node ;
198
+ }
199
+
200
+ return countWords (currentNode );
142
201
}
143
202
}
0 commit comments