Created
November 10, 2013 01:34
-
-
Save YanivHaramati/7392469 to your computer and use it in GitHub Desktop.
A simple trie in java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.HashMap; | |
import java.util.Map.Entry; | |
public class Trie { | |
private HashMap<Character, TNode> nodes = new HashMap<Character, TNode>(); | |
public Trie() {} | |
public void insert(String word) { | |
HashMap<Character, TNode> lNodes = nodes; | |
char[] letters = word.toCharArray(); | |
int length = letters.length - 1; | |
TNode current = null; | |
for (int i = 0; i <= length; i++){ | |
char c = letters[i]; | |
TNode tn = lNodes.get(c); | |
if (tn == null) { | |
tn = new TNode(c); | |
if (current != null) { | |
tn.parent = current; | |
} | |
if (i == length) { | |
tn.wordEnd = true; | |
} | |
lNodes.put(c, tn); | |
} | |
current = tn; | |
lNodes = tn.nodes; | |
} | |
} | |
public boolean contains(String word) { | |
HashMap<Character, TNode> lNodes = nodes; | |
char[] letters = word.toCharArray(); | |
int length = letters.length - 1; | |
for (int i = 0; i <= length; i++) { | |
char c = letters[i]; | |
TNode node = lNodes.get(c); | |
if (node == null) return false; | |
lNodes = node.nodes; | |
if (i == length && !node.wordEnd) return false; | |
} | |
return true; | |
} | |
public void delete(String word) { | |
HashMap<Character, TNode> lNodes = nodes; | |
char[] letters = word.toCharArray(); | |
int length = letters.length - 1; | |
// get to the end of the word | |
TNode current = null; | |
for (int i = 0; i <= length; i++) { | |
char c = letters[i]; | |
current = lNodes.get(c); | |
// if we don't have the word, do nothing. | |
if (current == null) return; | |
lNodes = current.nodes; | |
} | |
// if the word is a substring, just unmark it. | |
if (!current.nodes.isEmpty()) { | |
current.wordEnd = false; | |
return; | |
} | |
// otherwise we have to delete all the leafs that aren't marked as word ends. | |
for (int i = length; i >= 0; i--) { | |
char c = letters[i]; | |
if (current.nodes.isEmpty()) { | |
current = current.parent; | |
if (current == null) return; | |
if (!current.wordEnd) { | |
current.nodes.remove(c); | |
} | |
} | |
else { | |
return; | |
} | |
} | |
} | |
/** | |
* Recursively count words in the tree | |
* @return | |
*/ | |
public int count() { | |
return count(0, nodes); | |
} | |
public int count(int count, HashMap<Character, TNode> nodes) { | |
if (nodes.isEmpty()) return count + 0; | |
for (TNode node : nodes.values()) { | |
if (node.wordEnd) count++; | |
count += count(0, node.nodes); | |
} | |
return count; | |
} | |
public String toString() { | |
StringBuilder res = new StringBuilder(); | |
for (Entry<Character, TNode> kv : nodes.entrySet()) { | |
res.append("[" + kv.getKey() + ":" + kv.getValue() + "] "); | |
} | |
return res.toString(); | |
} | |
} | |
/** | |
* A trie node consists of a parent node (so we can backward traverse more efficiently when deleting letters.) | |
* A list of nodes flowing out of its representing character | |
* A character that represents this node | |
* A flag marking whether or not this is a word end. | |
* | |
* @author Yaniv | |
* | |
*/ | |
class TNode { | |
public TNode parent = null; | |
public HashMap<Character, TNode> nodes = new HashMap<Character, TNode>(); | |
public Character val = null; | |
public boolean wordEnd = false; | |
public TNode(char c) { | |
val = c; | |
} | |
public TNode(TNode p, char c) { | |
parent = p; | |
val = c; | |
} | |
public String toString() { | |
return String.format("%s : ", val) + nodes.keySet(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment