Skip to content

Commit 8817ee3

Browse files
committed
docs & style: Minor clarification in trie
1 parent ab12a8f commit 8817ee3

File tree

2 files changed

+34
-11
lines changed

2 files changed

+34
-11
lines changed

src/main/java/dataStructures/trie/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@ This flag is set to true for nodes that correspond to the final character of a c
1919
<em>Source: <a href="https://java2blog.com/trie-data-structure-in-java/">Java2Blog</a></em>
2020
</div>
2121

22+
### TrieNode
23+
A TrieNode represents a single node within a trie, which is a specialized tree-like data structure
24+
used primarily for storing strings in a compact format. It typically encapsulates the following:
25+
26+
1. Some kind of data structure to track children nodes; usually a HashMap or an array where indices represent
27+
alphabets (e.g. an array of size 26 for chars a-z)
28+
- Our implementation uses HashMap which is more versatile since it doesn't restrict the type of characters. But
29+
it is not uncommon to see nodes with int or char array. In fact, PS5 of CS2040s does this!
30+
2. Boolean flag to denote the end of a sequence of characters.
31+
3. Optional: Additional fields to augment the trie. For instance, one can track the weight of the subtree rooted at each node to
32+
easily query the number of words with some prefix.
33+
4. Optional: Parent pointer. Some trie implementations include a back-pointer to the node's parent. This is not required
34+
for basic trie operations but can be useful for certain algorithms that require traversing the trie in reverse,
35+
such as deletions or suffix trie constructions.
36+
- Our implementation features one such method where we prune the trie. But we used an array to track past nodes seen
37+
rather than rely on parent pointers.
38+
2239
## Complexity Analysis
2340
Let the length of the longest word be _L_ and the number of words be _N_.
2441

src/main/java/dataStructures/trie/Trie.java

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ public TrieNode() {
3737
public void insert(String word) {
3838
word = word.toLowerCase(); // ignore case-sensitivity
3939
TrieNode trav = root;
40+
char curr;
4041
for (int i = 0; i < word.length(); i++) {
41-
char curr = word.charAt(i);
42+
curr = word.charAt(i);
4243
if (!trav.children.containsKey(curr)) {
43-
trav.children.put(curr, new TrieNode()); // recall, the edges represent the characters
44+
trav.children.put(curr, new TrieNode()); // recall: new char is represented by this child node
4445
}
4546
trav = trav.children.get(curr);
4647
}
@@ -55,8 +56,9 @@ public void insert(String word) {
5556
public boolean search(String word) {
5657
word = word.toLowerCase();
5758
TrieNode trav = root;
59+
char curr;
5860
for (int i = 0; i < word.length(); i++) {
59-
char curr = word.charAt(i);
61+
curr = word.charAt(i);
6062
if (!trav.children.containsKey(curr)) {
6163
return false;
6264
}
@@ -72,8 +74,9 @@ public boolean search(String word) {
7274
public void delete(String word) {
7375
word = word.toLowerCase();
7476
TrieNode trav = root;
77+
char curr;
7578
for (int i = 0; i < word.length(); i++) {
76-
char curr = word.charAt(i);
79+
curr = word.charAt(i);
7780
if (!trav.children.containsKey(curr)) {
7881
return; // word does not exist in trie, so just return
7982
}
@@ -92,8 +95,9 @@ public void delete(String word) {
9295
public void deleteAndPrune(String word) {
9396
List<TrieNode> trackNodes = new ArrayList<>();
9497
TrieNode trav = root;
98+
char curr;
9599
for (int i = 0; i < word.length(); i++) {
96-
char curr = word.charAt(i);
100+
curr = word.charAt(i);
97101
if (!trav.children.containsKey(curr)) {
98102
return; // word does not exist in trie
99103
}
@@ -102,12 +106,14 @@ public void deleteAndPrune(String word) {
102106
}
103107
trav.isEnd = false;
104108

105-
// now we start pruning
106-
for (int i = word.length() - 1; i >= 0; i--) {
107-
char curr = word.charAt(i);
108-
TrieNode nodeBeforeCurr = trackNodes.get(i);
109-
TrieNode nextNode = nodeBeforeCurr.children.get(curr);
110-
if (!nextNode.isEnd && nextNode.children.size() == 0) { // node essentially doesn't track anything, remove
109+
// now, we start pruning
110+
TrieNode currNode; // nodes representing chars, where chars will be iterated from the back
111+
TrieNode nodeBeforeCurr;
112+
for (int i = word.length() - 1; i >= 0; i--) { // consider chars from back
113+
curr = word.charAt(i);
114+
nodeBeforeCurr = trackNodes.get(i);
115+
currNode = nodeBeforeCurr.children.get(curr);
116+
if (!currNode.isEnd && currNode.children.size() == 0) { // node essentially doesn't track anything, remove
111117
nodeBeforeCurr.children.remove(curr);
112118
} else { // children.size() > 0; i.e. this node is still useful; no need to further prune upwards
113119
break;

0 commit comments

Comments
 (0)