Skip to content

Instantly share code, notes, and snippets.

@YanivHaramati
Created November 10, 2013 01:34
Show Gist options
  • Save YanivHaramati/7392469 to your computer and use it in GitHub Desktop.
Save YanivHaramati/7392469 to your computer and use it in GitHub Desktop.
A simple trie in java
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