Skip to content

Commit 2033744

Browse files
authored
Refactor remove method and improve documentation
Updated remove method to return boolean instead of value. Improved documentation and refactored removeRecursive method.
1 parent 267c325 commit 2033744

File tree

1 file changed

+30
-45
lines changed

1 file changed

+30
-45
lines changed

src/main/java/com/thealgorithms/datastructures/tries/PatriciaTrie.java

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22

33
import java.util.HashMap;
44
import java.util.Map;
5-
import java.util.Objects;
65

76
/**
87
* Patricia (radix) trie for String keys and generic values.
98
*
10-
* <p>Edges are compressed: each child edge stores a non-empty String label.
11-
* Operations run in O(L) where L is the key length.</p>
9+
* <p>Compressed edges: each child edge stores a non-empty String label.
10+
* Operations are O(L) where L is the key length.</p>
1211
*
13-
* <p>Contract:
12+
* <p>Contracts:
1413
* <ul>
1514
* <li>Null keys are not allowed (IllegalArgumentException).</li>
1615
* <li>Empty-string key ("") is allowed as a valid key.</li>
@@ -76,39 +75,28 @@ public boolean contains(String key) {
7675
}
7776

7877
/**
79-
* Removes the mapping for {@code key} if present.
78+
* Removes {@code key} if present.
8079
*
81-
* <p>Fixes for CI failures:
82-
* - Properly removes leaf nodes and decrements size once.
83-
* - Merges redundant pass-through nodes (no value, single child) by
84-
* concatenating edge labels.</p>
80+
* <p>Also compacts pass-through nodes (no value + single child) by concatenating
81+
* edge labels to keep the trie compressed.</p>
8582
*
8683
* @param key non-null key
87-
* @return previous value or {@code null} if none
84+
* @return true if the key existed and was removed
8885
*/
89-
public V remove(String key) {
86+
public boolean remove(String key) {
9087
if (key == null) {
91-
throw new IllegalArgumentException("key cannot be null");
88+
throw new IllegalArgumentException("key must not be null");
9289
}
9390
if (key.isEmpty()) {
9491
if (!root.hasValue) {
95-
return null;
92+
return false;
9693
}
97-
V old = root.value;
9894
root.hasValue = false;
9995
root.value = null;
10096
size--;
101-
return old;
97+
return true;
10298
}
103-
104-
// container to return "was removed" + old value up the recursion
105-
Object[] removedHolder = new Object[1];
106-
removeRecursive(root, key, removedHolder);
107-
108-
if (removedHolder[0] != null) {
109-
size--;
110-
}
111-
return (V) removedHolder[0];
99+
return removeRecursive(root, key);
112100
}
113101

114102
/**
@@ -269,9 +257,10 @@ private Node<V> findPrefixNode(Node<V> node, String prefix) {
269257
* </ul>
270258
* </p>
271259
*/
272-
private void removeRecursive(Node<V> parent, String key, Object[] removedHolder) {
260+
private boolean removeRecursive(Node<V> parent, String key) {
273261
// iterate on a snapshot of keys to allow modifications during loop
274-
for (String edge : parent.children.keySet().toArray(new String[0])) {
262+
String[] keys = parent.children.keySet().toArray(new String[0]);
263+
for (String edge : keys) {
275264
int cpl = commonPrefixLen(edge, key);
276265
if (cpl == 0) {
277266
continue;
@@ -281,20 +270,25 @@ private void removeRecursive(Node<V> parent, String key, Object[] removedHolder)
281270

282271
// partial overlap with edge => key doesn't exist in this branch
283272
if (cpl < edge.length()) {
284-
return;
273+
return false;
285274
}
286275

287276
String rest = key.substring(cpl);
277+
boolean removed;
288278
if (rest.isEmpty()) {
289-
// we've reached the node that holds the key
290-
if (child.hasValue) {
291-
removedHolder[0] = child.value;
292-
child.hasValue = false;
293-
child.value = null;
279+
if (!child.hasValue) {
280+
return false;
294281
}
282+
child.hasValue = false;
283+
child.value = null;
284+
size--;
285+
removed = true;
295286
} else {
296-
// keep traversing
297-
removeRecursive(child, rest, removedHolder);
287+
removed = removeRecursive(child, rest);
288+
}
289+
290+
if (!removed) {
291+
return false;
298292
}
299293

300294
// post-recursion cleanup of child
@@ -314,8 +308,9 @@ private void removeRecursive(Node<V> parent, String key, Object[] removedHolder)
314308
parent.children.put(edge + grandEdge, grand);
315309
}
316310
}
317-
return; // processed the matching path
311+
return true; // processed the matching path
318312
}
313+
return false;
319314
}
320315

321316
/** Length of common prefix of a and b. */
@@ -327,14 +322,4 @@ private static int commonPrefixLen(String a, String b) {
327322
}
328323
return i;
329324
}
330-
331-
@Override
332-
public int hashCode() {
333-
return Objects.hash(size);
334-
}
335-
336-
@Override
337-
public boolean equals(Object obj) {
338-
return this == obj;
339-
}
340325
}

0 commit comments

Comments
 (0)