How to find the longest word in a prefix tree recursiverly? - java

I have the following data structure:
This tree stores only characters in lowercase.
I'm trying to build a method that finds the longest word in the tree recursively.
I have difficulty to build this method that checks each branch of the nodes recursively.
Here the given classes I'm using, showing only the relevant methods:
public class Tree {
private final Node root;
public Tree() {
root = new Node('0');
}
private String getWordOfBranch(final Node[] nodes, final int i) {
if (nodes[i] == null) {
return "";
}
if (nodes[i].isLeaf()) {
return String.valueOf(nodes[i].getValue());
}
return nodes[i].getValue() + getWordOfBranch(nodes[i].children, i);
}
public class Node {
private final char value;
protected Node[] children;
public Node(final char value) {
this.value = value;
children = new Node[26];
}
public boolean isLeaf() {
for (final Node child : children) {
if (child != null) {
return false;
}
}
return true;
}
public char getValue() {
return value;
}

Well, in this case, you are only taking the word starting at a specific position i. What you should be doing is looping through all of the children and finding the longest word out of all of the children. Also, your node class should not be having a set amount of children, but instead a dynamically sized list of children, using something like an ArrayList to store the children, since each node does not have to have a specific set of children.
public class Node {
private final char value;
protected ArrayList<Node> children;
public Node(final char value) {
this.value = value;
children = new ArrayList<Node>();
}
public boolean isLeaf() {
for (final Node child : children) {
if (child != null) {
return false;
}
}
return true;
}
public char getValue() {
return value;
}
public ArrayList<Node> getChildren() {
return children;
}
public String getLargestWord(Node root) {
if (root.isLeaf()) {
return String.valueOf(root.getValue());
}
else {
String longest = "";
for (Node child : root.getChildren()) {
String longWordInChild = getLongestWord(child);
if (longWordInChild.length() > longest.length()) {
longest = longWordInChild;
}
}
return root.getValue() + longest;
}
}

I made some changes to your code.
First the Node class.
import java.util.ArrayList;
import java.util.List;
public class Node {
private final char value;
protected List<Node> children;
public Node(char letter) {
value = letter;
children = new ArrayList<>();
}
private static boolean isValidValue(Node node) {
boolean isValid = false;
if (node != null) {
char ch = node.getValue();
isValid = 'a' <= ch && ch <= 'z';
}
return isValid;
}
public boolean addChild(Node child) {
boolean added = false;
if (child != null) {
if (isValidValue(child)) {
boolean found = false;
for (Node kid : children) {
found = kid != null && kid.getValue() == child.getValue();
if (found) {
break;
}
}
if (!found) {
added = children.add(child);
}
}
}
return added;
}
public List<Node> getChildren() {
return children;
}
public char getValue() {
return value;
}
}
I used List for the children, rather than an array, because an array has a fixed size and a List does not.
Now the Tree class. Note that I added a main() method to the class just for testing purposes. The main() method creates the tree structure in the image in your question.
A tree data structure has levels and also has leaves. A leaf is a node in the tree that has no child nodes. Hence every leaf in your tree is the last letter of a word. The leaves at the highest level represent the longest words. (Note that the level of the root node in the tree is zero.)
import java.util.ArrayList;
import java.util.List;
public class Tree {
private int longest;
private List<String> words;
private Node root = new Node('\u0000');
public List<String> getWords() {
return words;
}
public Node getRoot() {
return root;
}
public void visit() {
visit(root, 0, new StringBuilder());
}
public void visit(Node node, int level, StringBuilder word) {
if (node != null) {
word.append(node.getValue());
List<Node> children = node.getChildren();
if (children.size() == 0) {
if (level > longest) {
longest = level;
words = new ArrayList<>();
}
if (level == longest) {
words.add(word.toString());
}
}
else {
for (Node child : children) {
word.delete(level, word.length());
visit(child, level + 1, word);
}
}
}
}
/**
* For testing only.
*/
public static void main(String[] args) {
Tree tree = new Tree();
Node root = tree.getRoot();
Node j = new Node('j');
root.addChild(j);
Node r = new Node('r');
root.addChild(r);
Node a = new Node('a');
j.addChild(a);
Node v = new Node('v');
a.addChild(v);
Node a2 = new Node('a');
v.addChild(a2);
Node a3 = new Node('a');
r.addChild(a3);
Node o = new Node('o');
r.addChild(o);
Node d = new Node('d');
a3.addChild(d);
Node n = new Node('n');
a3.addChild(n);
Node d2 = new Node('d');
n.addChild(d2);
Node u = new Node('u');
a3.addChild(u);
Node m = new Node('m');
u.addChild(m);
Node s = new Node('s');
o.addChild(s);
Node e = new Node('e');
s.addChild(e);
tree.visit();
System.out.println(tree.getWords());
}
}
Method visit(Node, int, StringBuilder) is the recursive method. It traverses every path in the tree and appends the characters in each node to a StringBuilder. Hence the StringBuilder contains the word obtained by traversing a single path in the tree - from the root to the leaf.
I also keep track of the node level since the highest level means the longest word.
Finally I store all the longest words in another List.
Running the above code produces the following output:
[java, rand, raum, rose]

Related

Implementing an insert into a Binary Search Tree with a String Object JAVA

Im trying to implement a program that adds Word Objects(string word, string meaning) into a Binary Search Tree Alphabetically. I know how to implement a Binary Search Tree with an integer attribute but I'm having difficulties doing it with strings.
public class WordInfo {
public String word;
public String meaning;
public WordInfo left;
public WordInfo right;
public WordInfo(String word, String meaning){
this.word = word;
this.meaning = meaning;
left=right = null;
}
}
public class Dictionary {
WordInfo root;
int count;
public Dictionary() {
root = null;
}
public void add(String word, String meaning) {
WordInfo w = new WordInfo(word, meaning);
if (root == null) {
root = w;
}
WordInfo curr, parent;
parent = curr = root;
while (curr != null) {
parent = curr;
if (word.compareToIgnoreCase(curr.word) < 0) {
curr = curr.left;
} else {
curr = curr.right;
}
}
if (word.compareToIgnoreCase(parent.word) < 0) {
parent.left = w;
} else {
parent.right = w;
}
} }
When I try to add these WordInfo objects into my main program nothing is being added.
In your code snippet, you haven't returned if empty dictionary.
if (root == null) {
root = w;
}
have to be replaced with
if (root == null) {
root = w;
return;
}
So if the root is null, you add an element and return it, of course you can increment the count when new element added.

Java Level order to N-Ary tree (Iterative and not recursion)

trying to convert a level order input to a N-Ary tree. Where levels are separated by a null. Example.
Input: [1, null, 2,3,4, null,5,6,null,7,8,null,9,10]
Code is expected to build a tree and finally print the preorder of the same for validation.
Output: [1,2,5,6, 3,7,8,4,9,10]
Not getting the desired output. Also this needs to be solved iteratively and recursion may not be used. Below is the full code. Added some print statement to ease debugging.
enter code here
package AllTree;
import java.util.*;
public class ListToNArrayTree {
public static class Node{
public int val;
public ArrayList<Node> children = new ArrayList<>();
public Node (int val){
this.val = val;
}
public Node (int val, ArrayList<Node> children){
this.val = val;
this.children = children;
}
public String toString(){
return " " + val;
}
public ArrayList<Node> getChildren() {
return children;
}
public void setChildren(ArrayList<Node> children) {
this.children = children;
}
}
public static Node buildTree(List<Integer> dataAsList){
/*Check if the input is valid to create a tree example {1, null, 2,3,4, null,5,6,null,7,8,null,9,10, null};
Above is a level order so null is mandatory # position 1.
*/
if (dataAsList.isEmpty() || dataAsList.get(0) == null|| dataAsList.get(1) !=null){
System.out.println ("Invalid data to construct a tree");
return null;
}
/*Create queue to hold all values from input*/
Queue<Integer> dataAsQueue = new LinkedList<>();
for (Integer data: dataAsList) {
dataAsQueue.add(data);
}
/*Create queue to hold the nodes which will be retrieved in FIFO to add corresponding children*/
Queue<Node> dataAsTree = new LinkedList<>();
Node root = new Node(dataAsQueue.poll()); // to poll the root element
dataAsQueue.poll(); // to poll the null - as after this is the beginning of the second level of the tree
dataAsTree.add(root);
root = dataAsTree.poll();
Node parent = root;
while (!dataAsQueue.isEmpty()) {
Node parent_ = parent;
Integer childInt= dataAsQueue.poll();
if (childInt != null){
parent_.getChildren().add(new Node(childInt));
dataAsTree.add(new Node(childInt));
}
else{
parent = dataAsTree.poll();
}
System.out.println ("Current parent " + parent_ + " with children" + parent_.children);
}
return root;
}
public static void main(String[] args){
List<Integer> dataAsList = Arrays.asList(1, null, 2,3,4, null,5,6,null,7,8,null,9,10);
// Node root = buildTree(dataAsList);
System.out.println ("PreOrder Sorting" + preorder( buildTree(dataAsList)));
}
public static List<Integer> preorder(Node root) {
LinkedList<Integer> res = new LinkedList<>();
if (root == null) {
return res;
}
preorderhelper(root, res);
return res;
}
private static void preorderhelper(Node root, LinkedList<Integer> res) {
if (root == null) {
return;
}
res.add(root.val);
if (root.children != null) {
for (Node c : root.children) {
preorderhelper(c, res);
}
}
}
}

Infinite loop when replacing a node in an unsorted tree

I'm doing a homework assignment in Java where I have to create an unsorted binary tree with a String as the data value. I then have to write a function that replaces a Node and any duplicate Nodes that match an old description with a new object that contains a new description.
Here is the code that I am working with, including the test case that causes an infinite loop:
public class Node {
private String desc;
private Node leftNode = null;
private Node rightNode = null;
private int height;
public Node(String desc) {
this.desc = desc;
height = 0; // assumes that a leaf node has a height of 0
}
public String getDesc() {
return desc;
}
public Node getLeftNode() {
return leftNode;
}
public Node getRightNode() {
return rightNode;
}
public void setLeftNode(Node node) {
++height;
leftNode = node;
}
public void setRightNode(Node node) {
++height;
rightNode = node;
}
public int getHeight() {
return height;
}
public int addNode(Node node) {
if(leftNode == null) {
setLeftNode(node);
return 1;
}
if(rightNode == null) {
setRightNode(node);
return 1;
}
if(leftNode.getHeight() <= rightNode.getHeight()) {
leftNode.addNode(node);
++height;
} else {
rightNode.addNode(node);
++height;
}
return 0;
}
public static void displayTree(Node root) {
if(root != null) {
displayTree(root.getLeftNode());
System.out.println(root.getDesc());
displayTree(root.getRightNode());
}
}
public static Node findNode(Node current, String desc) {
Node result = null;
if(current == null) {
return null;
}
if(current.getDesc().equals(desc)) {
return current;
}
if(current.getLeftNode() != null) {
result = findNode(current.getLeftNode(), desc);
}
if(result == null) {
result = findNode(current.getRightNode(), desc);
}
return result;
}
public static void replaceNode(Node root, String oldDesc, String newDesc) {
if(oldDesc == null || newDesc == null) {
System.out.println("Invalid string entered");
return;
}
boolean replacedAllNodes = false;
while(replacedAllNodes == false) {
Node replace = findNode(root, oldDesc);
if(replace == null) { // No more nodes to replace
replacedAllNodes = true;
return;
}
replace = new Node(newDesc);
root.addNode(replace);
}
return;
}
public static void main(String[] args) {
Node root = new Node("test1");
Node test_2 = new Node("test2");
Node test_3 = new Node("test3");
Node test_4 = new Node("test4");
Node test_5 = new Node("test5");
Node test_6 = new Node("test6");
root.addNode(test_2);
root.addNode(test_3);
root.addNode(test_4);
root.addNode(test_5);
root.addNode(test_6);
displayTree(root);
replaceNode(root, "test4", "hey");
System.out.println("-------");
displayTree(root);
}
}
After testing the findNode method, and seeing that it returns the correct object, I realized that the infinite loop was being caused by my replaceNode method. I'm just not really sure how it is causing it.
I got it to work with one case by removing the while loop, but obviously that won't work for duplicates, so I'm wondering how I could remove the node with oldDesc and replace it with a new object that contains newDesc when there could be multiple objects with matching oldDesc data.
you are never changing root or oldDesc in your while loop
while(replacedAllNodes == false) {
Node replace = findNode(root, oldDesc);
if(replace == null) { // No more nodes to replace
replacedAllNodes = true;
return;
}
replace = new Node(newDesc);
root.addNode(replace);
}
If you watch
public static Node findNode(Node current, String desc) {
Node result = null;
if(current == null) {
return null;
}
if(current.getDesc().equals(desc)) {
return current;
}
if(current.getLeftNode() != null) {
result = findNode(current.getLeftNode(), desc);
}
if(result == null) {
result = findNode(current.getRightNode(), desc);
}
return result;
}
If the if(current.getDesc().equals(desc)) condition matches, replace will always be root so you are stuck in your while loop
Update:
If you dont necessarily have to replace the whole node, you could just update the description for your node at the end of your while loop.
instead of
replace = new Node(newDesc);
root.addNode(replace);
do something like:
root.setDesc(newDesc);
(of course you would have to create a setDesc() method first)
If you have to replace the whole object, you have to go like this:
Instead of
replace = new Node(newDesc);
root.addNode(replace);
do something like this:
replace = new Node(newDesc);
replace.setLeftNode(root.getLeftNode);
replace.setRightNode(root.getRightNode);
Plus you have to link the node that pointed to root so it points to replace like one of the following examples (depends on which side your root was of course):
nodeThatPointedToRoot.setLeftNode(replace);
nodeThatPointedToRoot.setRightNode(replace);
well looking at your code, you are not replacing a node you are just adding a new node to the edge of the tree and the old node would still be there so the loop will go forever and you can add a temp variable with an auto increment feature and to indicate the level of the node you are reaching to replace and you'll find it's just doing it again and again, instead of doing all this process how about just replacing the description inside that node ?

Get Words out of a Trie Data Structure

i have the following Trie Data Structure:
public class CDictionary implements IDictionary {
private static final int N = 'z' -'a'+1;
private static class Node {
private boolean end = false;
private Node[] next = new Node[N];
}
private int size = 0;
private Node root = new Node();
#Override
public boolean contains(String word) {
Node node = this.contains(root,word,0);
if (node == null) {
return false;
}
return node.end;
}
private Node contains(Node node, String str, int d) {
if (node == null) return null;
if (d == str.length()) return node;
char c = str.charAt(d);
return contains(node.next[c-'a'], str, d+1);
}
#Override
public void insert(String word) {
this.root = insert(this.root, word, 0);
this.size++;
}
private Node insert(Node node, String str, int d) {
if (node == null) node = new Node();
if (d == str.length()) {
node.end = true;
return node;
}
char c = str.charAt(d);
node.next[c-'a'] = this.insert(node.next[c-'a'], str, d+1);
return node;
}
#Override
public int size() {
return size;
}
The Trie is filled with some words like
for, the, each, home, is, it, egg, red...
Now i need a function to get all Words with a specific length for example the length 3
public List<String> getWords(int lenght) {
}
With the Words mentioned above it should return a list with the words
for,the,egg,red
The Problem is how can i restore these words out of the Trie Structur?
You need to recurse through your structure to a maximum depth of N (in this case 3)
You could do this by adding a couple of methods to your dictionary...
public List<String> findWordsOfLength(int length) {
// Create new empty list for results
List<String> results = new ArrayList<>();
// Start at the root node (level 0)...
findWordsOfLength(root, "", 0, length, results);
// Return the results
return results;
}
public void findWordsOfLength(Node node, String wordSoFar, int depth, int maxDepth, List<String> results) {
// Go through each "child" of this node
for(int k = 0; k < node.next.length; k++) {
Node child = node.next[k];
// If this child exists...
if(child != null) {
// Work out the letter that this child represents
char letter = 'a' + k;
// If we have reached "maxDepth" letters...
if(depth == maxDepth) {
// Add this letter to the end of the word so far and then add the word to the results list
results.add(wordSoFar + letter);
} else {
// Otherwise recurse to the next level
findWordsOfLength(child, wordSoDar + letter, depth + 1, maxDepth, results);
}
}
}
}
(I have not compiled / tested this, but it should give you an idea of what you need to do)
Hope this helps.

Getting a list of words from a Trie

I'm looking to use the following code to not check whether there is a word matching in the Trie but to return a list all words beginning with the prefix inputted by the user. Can someone point me in the right direction? I can't get it working at all.....
public boolean search(String s)
{
Node current = root;
System.out.println("\nSearching for string: "+s);
while(current != null)
{
for(int i=0;i<s.length();i++)
{
if(current.child[(int)(s.charAt(i)-'a')] == null)
{
System.out.println("Cannot find string: "+s);
return false;
}
else
{
current = current.child[(int)(s.charAt(i)-'a')];
System.out.println("Found character: "+ current.content);
}
}
// If we are here, the string exists.
// But to ensure unwanted substrings are not found:
if (current.marker == true)
{
System.out.println("Found string: "+s);
return true;
}
else
{
System.out.println("Cannot find string: "+s +"(only present as a substring)");
return false;
}
}
return false;
}
}
I faced this problem while trying to make a text auto-complete module. I solved the problem by making a Trie in which each node contains it's parent node as well as children. First I searched for the node starting at the input prefix. Then I applied a Traversal on the Trie that explores all the nodes of the sub-tree with it's root as the prefix node. whenever a leaf node is encountered, it means that the end of a word starting from input prefix has been found. Starting from that leaf node I iterate through the parent nodes getting parent of parent, and reach the root of the subtree. While doing so I kept adding the keys of nodes in a stack. In the end I took the prefix and started appended it by popping the stack. I kept on saving the words in an ArrayList. At the end of the traversal I get all the words starting from the input prefix. Here is the code with usage example:
class TrieNode
{
char c;
TrieNode parent;
HashMap<Character, TrieNode> children = new HashMap<Character, TrieNode>();
boolean isLeaf;
public TrieNode() {}
public TrieNode(char c){this.c = c;}
}
-
public class Trie
{
private TrieNode root;
ArrayList<String> words;
TrieNode prefixRoot;
String curPrefix;
public Trie()
{
root = new TrieNode();
words = new ArrayList<String>();
}
// Inserts a word into the trie.
public void insert(String word)
{
HashMap<Character, TrieNode> children = root.children;
TrieNode crntparent;
crntparent = root;
//cur children parent = root
for(int i=0; i<word.length(); i++)
{
char c = word.charAt(i);
TrieNode t;
if(children.containsKey(c)){ t = children.get(c);}
else
{
t = new TrieNode(c);
t.parent = crntparent;
children.put(c, t);
}
children = t.children;
crntparent = t;
//set leaf node
if(i==word.length()-1)
t.isLeaf = true;
}
}
// Returns if the word is in the trie.
public boolean search(String word)
{
TrieNode t = searchNode(word);
if(t != null && t.isLeaf){return true;}
else{return false;}
}
// Returns if there is any word in the trie
// that starts with the given prefix.
public boolean startsWith(String prefix)
{
if(searchNode(prefix) == null) {return false;}
else{return true;}
}
public TrieNode searchNode(String str)
{
Map<Character, TrieNode> children = root.children;
TrieNode t = null;
for(int i=0; i<str.length(); i++)
{
char c = str.charAt(i);
if(children.containsKey(c))
{
t = children.get(c);
children = t.children;
}
else{return null;}
}
prefixRoot = t;
curPrefix = str;
words.clear();
return t;
}
///////////////////////////
void wordsFinderTraversal(TrieNode node, int offset)
{
// print(node, offset);
if(node.isLeaf==true)
{
//println("leaf node found");
TrieNode altair;
altair = node;
Stack<String> hstack = new Stack<String>();
while(altair != prefixRoot)
{
//println(altair.c);
hstack.push( Character.toString(altair.c) );
altair = altair.parent;
}
String wrd = curPrefix;
while(hstack.empty()==false)
{
wrd = wrd + hstack.pop();
}
//println(wrd);
words.add(wrd);
}
Set<Character> kset = node.children.keySet();
//println(node.c); println(node.isLeaf);println(kset);
Iterator itr = kset.iterator();
ArrayList<Character> aloc = new ArrayList<Character>();
while(itr.hasNext())
{
Character ch = (Character)itr.next();
aloc.add(ch);
//println(ch);
}
// here you can play with the order of the children
for( int i=0;i<aloc.size();i++)
{
wordsFinderTraversal(node.children.get(aloc.get(i)), offset + 2);
}
}
void displayFoundWords()
{
println("_______________");
for(int i=0;i<words.size();i++)
{
println(words.get(i));
}
println("________________");
}
}//
Example
Trie prefixTree;
prefixTree = new Trie();
prefixTree.insert("GOING");
prefixTree.insert("GONG");
prefixTree.insert("PAKISTAN");
prefixTree.insert("SHANGHAI");
prefixTree.insert("GONDAL");
prefixTree.insert("GODAY");
prefixTree.insert("GODZILLA");
if( prefixTree.startsWith("GO")==true)
{
TrieNode tn = prefixTree.searchNode("GO");
prefixTree.wordsFinderTraversal(tn,0);
prefixTree.displayFoundWords();
}
if( prefixTree.startsWith("GOD")==true)
{
TrieNode tn = prefixTree.searchNode("GOD");
prefixTree.wordsFinderTraversal(tn,0);
prefixTree.displayFoundWords();
}
After building Trie, you could do DFS starting from node, where you found prefix:
Here Node is Trie node, word=till now found word, res = list of words
def dfs(self, node, word, res):
# Base condition: when at leaf node, add current word into our list
if EndofWord at node:
res.append(word)
return
# For each level, go deep down, but DFS fashion
# add current char into our current word.
for w in node:
self.dfs(node[w], word + w, res)
The simplest solution is to use a depth-first search.
You go down the trie, matching letter by letter from the input. Then, once you have no more letter to match, everything under that node are strings that you want. Recursively explore that whole subtrie, building the string as you go down to its nodes.
This is easier to solve recursively in my opinion. It would go something like this:
Write a recursive function Print that prints all the nodes in the trie rooted in the node you give as parameter. Wiki tells you how to do this (look at sorting).
Find the last character of your prefix, and the node that is labeled with the character, going down from the root in your trie. Call the Print function with this node as the parameter. Then just make sure you also output the prefix before each word, since this will give you all the words without their prefix.
If you don't really care about efficiency, you can just run Print with the main root node and only print those words that start with the prefix you're interested in. This is easier to implement but slower.
You need to traverse the sub-tree starting at the node you found for the prefix.
Start in the same way, i.e. finding the correct node. Then, instead of checking its marker, traverse that tree (i.e. go over all its descendants; a DFS is a good way to do it) , saving the substring used to reach the "current" node from the first node.
If the current node is marked as a word, output* the prefix + substring reached.
* or add it to a list or something.
I built a trie once for one of ITA puzzles
public class WordTree {
class Node {
private final char ch;
/**
* Flag indicates that this node is the end of the string.
*/
private boolean end;
private LinkedList<Node> children;
public Node(char ch) {
this.ch = ch;
}
public void addChild(Node node) {
if (children == null) {
children = new LinkedList<Node>();
}
children.add(node);
}
public Node getNode(char ch) {
if (children == null) {
return null;
}
for (Node child : children) {
if (child.getChar() == ch) {
return child;
}
}
return null;
}
public char getChar() {
return ch;
}
public List<Node> getChildren() {
if (this.children == null) {
return Collections.emptyList();
}
return children;
}
public boolean isEnd() {
return end;
}
public void setEnd(boolean end) {
this.end = end;
}
}
Node root = new Node(' ');
public WordTree() {
}
/**
* Searches for a strings that match the prefix.
*
* #param prefix - prefix
* #return - list of strings that match the prefix, or empty list of no matches are found.
*/
public List<String> getWordsForPrefix(String prefix) {
if (prefix.length() == 0) {
return Collections.emptyList();
}
Node node = getNodeForPrefix(root, prefix);
if (node == null) {
return Collections.emptyList();
}
List<LinkedList<Character>> chars = collectChars(node);
List<String> words = new ArrayList<String>(chars.size());
for (LinkedList<Character> charList : chars) {
words.add(combine(prefix.substring(0, prefix.length() - 1), charList));
}
return words;
}
private String combine(String prefix, List<Character> charList) {
StringBuilder sb = new StringBuilder(prefix);
for (Character character : charList) {
sb.append(character);
}
return sb.toString();
}
private Node getNodeForPrefix(Node node, String prefix) {
if (prefix.length() == 0) {
return node;
}
Node next = node.getNode(prefix.charAt(0));
if (next == null) {
return null;
}
return getNodeForPrefix(next, prefix.substring(1, prefix.length()));
}
private List<LinkedList<Character>> collectChars(Node node) {
List<LinkedList<Character>> chars = new ArrayList<LinkedList<Character>>();
if (node.getChildren().size() == 0) {
chars.add(new LinkedList<Character>(Collections.singletonList(node.getChar())));
} else {
if (node.isEnd()) {
chars.add(new LinkedList<Character>
Collections.singletonList(node.getChar())));
}
List<Node> children = node.getChildren();
for (Node child : children) {
List<LinkedList<Character>> childList = collectChars(child);
for (LinkedList<Character> characters : childList) {
characters.push(node.getChar());
chars.add(characters);
}
}
}
return chars;
}
public void addWord(String word) {
addWord(root, word);
}
private void addWord(Node parent, String word) {
if (word.trim().length() == 0) {
return;
}
Node child = parent.getNode(word.charAt(0));
if (child == null) {
child = new Node(word.charAt(0));
parent.addChild(child);
} if (word.length() == 1) {
child.setEnd(true);
} else {
addWord(child, word.substring(1, word.length()));
}
}
public static void main(String[] args) {
WordTree tree = new WordTree();
tree.addWord("world");
tree.addWord("work");
tree.addWord("wolf");
tree.addWord("life");
tree.addWord("love");
System.out.println(tree.getWordsForPrefix("wo"));
}
}
You would need to use a List
List<String> myList = new ArrayList<String>();
if(matchingStringFound)
myList.add(stringToAdd);
After your for loop, add a call to printAllStringsInTrie(current, s);
void printAllStringsInTrie(Node t, String prefix) {
if (t.current_marker) System.out.println(prefix);
for (int i = 0; i < t.child.length; i++) {
if (t.child[i] != null) {
printAllStringsInTrie(t.child[i], prefix + ('a' + i)); // does + work on (String, char)?
}
}
}
The below recursive code can be used where your TrieNode is like this:
This code works fine.
TrieNode(char c)
{
this.con=c;
this.isEnd=false;
list=new ArrayList<TrieNode>();
count=0;
}
//--------------------------------------------------
public void Print(TrieNode root1, ArrayList<Character> path)
{
if(root1==null)
return;
if(root1.isEnd==true)
{
//print the entire path
ListIterator<Character> itr1=path.listIterator();
while(itr1.hasNext())
{
System.out.print(itr1.next());
}
System.out.println();
return;
}
else{
ListIterator<TrieNode> itr=root1.list.listIterator();
while(itr.hasNext())
{
TrieNode child=itr.next();
path.add(child.con);
Print(child,path);
path.remove(path.size()-1);
}
}
Simple recursive DFS algorithm can be used to find all words for a given prefix.
Sample Trie Node:
static class TrieNode {
Map<Character, TrieNode> children = new HashMap<>();
boolean isWord = false;
}
Method to find all words for a given prefix:
static List<String> findAllWordsForPrefix(String prefix, TrieNode root) {
List<String> words = new ArrayList<>();
TrieNode current = root;
for(Character c: prefix.toCharArray()) {
TrieNode nextNode = current.children.get(c);
if(nextNode == null) return words;
current = nextNode;
}
if(!current.children.isEmpty()) {
findAllWordsForPrefixRecursively(prefix, current, words);
} else {
if(current.isWord) words.add(prefix);
}
return words;
}
static void findAllWordsForPrefixRecursively(String prefix, TrieNode node, List<String> words) {
if(node.isWord) words.add(prefix);
if(node.children.isEmpty()) {
return;
}
for(Character c: node.children.keySet()) {
findAllWordsForPrefixRecursively(prefix + c, node.children.get(c), words);
}
}
Complete code can be found at below:
TrieDataStructure Example

Categories