I am trying ti implement the insert method of the Patricia Trie data structure but I have the feeling I wrote to many code lines. Please can someone tell me where can I call the method insert(TrieNode nodeRoot, String s) rekursiv?
Code:
private void insert(TrieNode nodeRoot, String s) {
int len1 = nodeRoot.value.length();
int len2 = s.length();
int len = Math.min(len1, len2);
for (int index = 0; index < len; index++) {
if (s.charAt(index) != nodeRoot.value.charAt(index)) {
// In case the both words have common substrings and after the
// common substrings the words are split.
String samesubString = s.substring(0, index);
String substringSplit1 = nodeRoot.value.substring(index);
String substringSplit2 = s.substring(index);
if (!samesubString.isEmpty()) {
nodeRoot.value = samesubString;
}
TrieNode nodeLeft = new TrieNode(substringSplit1);
nodeLeft.isWord = true;
TrieNode nodeRight = new TrieNode(substringSplit2);
nodeRight.isWord = true;
if (nodeRoot.getNext() != null && !nodeRoot.getNext().isEmpty()) {
checkTheValieAvialable(nodeRoot, s, nodeRight);
} else {
nodeRoot.next.add(nodeLeft);
nodeRoot.next.add(nodeRight);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
}
break;
} else if (index == (s.length() - 1)
|| index == (nodeRoot.value.length() - 1)) {
// In case the node just needs one path since one word is
// substring of the other.
// For example (aba and abac)
if (len1 > len2) {
// root value is longer
System.out.println("root value is longer");
String samesubString = nodeRoot.value.substring(0,
index + 1);
String different = nodeRoot.value.substring(index + 1);
if (nodeRoot.getNext() != null
&& !nodeRoot.getNext().isEmpty()) {
for (TrieNode subword : nodeRoot.getNext()) {
String subword2 = subword.getValue();
boolean contains = different.contains(subword2);
if (contains) {
String[] split = different.split(subword2);
TrieNode leaf1 = new TrieNode(split[1]);
leaf1.isWord = true;
subword.next.add(leaf1);
System.out.println("Test.");
}
}
} else {
String substringSplit1 = nodeRoot.value.substring(index + 1);
nodeRoot.value = samesubString;
TrieNode leaf = new TrieNode(substringSplit1);
leaf.isWord = true;
nodeRoot.next.add(leaf);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
}
String substringSplit1 = nodeRoot.value
.substring(index + 1);
nodeRoot.value = samesubString;
nodeRoot.isWord = true;
TrieNode leaf = new TrieNode(substringSplit1);
leaf.isWord = true;
nodeRoot.next.add(leaf);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
} else {
// new inserted string value is longer. For example (abac and aba).
System.out.println("instered is longer");
String samesubString = s.substring(0, index + 1);
String different = s.substring(index + 1);
if (nodeRoot.getNext() != null
&& !nodeRoot.getNext().isEmpty()) {
for (TrieNode subword : nodeRoot.getNext()) {
String subword2 = subword.getValue();
boolean contains = different.contains(subword2);
if (contains) {
String[] split = different.split(subword2);
TrieNode leaf1 = new TrieNode(split[1]);
leaf1.isWord = true;
subword.next.add(leaf1);
System.out.println("Test.");
}
}
} else {
String substringSplit1 = s.substring(index + 1);
s = samesubString;
TrieNode parentLeaf = new TrieNode(s);
parentLeaf.isWord = true;
TrieNode leaf = new TrieNode(substringSplit1);
leaf.isWord = true;
nodeRoot.next.add(leaf);
for (TrieNode subword : nodeRoot.getNext()) {
System.out.println(nodeRoot.getValue() + "---"
+ subword.getValue());
}
}
}
} else {
System.out.println("They are the same - " + index);
}
}
}
TrieNode class:
package patriciaTrie;
import java.util.ArrayList;
public class TrieNode {
ArrayList<TrieNode> next = new ArrayList<TrieNode>();
String value;
boolean isWord;
TrieNode(String value){
this.value = value;
}
public ArrayList<TrieNode> getNext() {
return next;
}
public void setNext(ArrayList<TrieNode> next) {
this.next = next;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
While using recursion please consider the steps:
Base condition
Logic (if any)
Recursive call.
Ex. for factorial of number:
int fact(int n)
{
if(n==0 || n==1)
return 1; // Base condition
return n * fact(n-1); // Recursive call
}
Applying the same concept in Trie:
base condition is: while traversing through a path, if we have reached leaf, current string is not in trie, then create a new edge or node and add remaining character to it.
Recursively call the insert if we have found a matching node. And if a matching node doen't exist create a new path with common parent.
You can take help from link : http://www.geeksforgeeks.org/trie-insert-and-search/
The best way to approach to problem recursively is to identify base condition in a problem.
Related
I need to navigate my 23Tree and print all the levels and corresponding elements. However, my recursion goes in any one direction and does not return and perform other calls. Any help would be much appreciated.
Here is my node class:
class Node<T extends Comparable<T>> {
List<T> vals = new ArrayList<T>();
List<Node<T>> children = new ArrayList<Node<T>>();
boolean isLeaf() { return children.size() == 0; }
boolean is4Node() { return vals.size() == 3; }
// new Nodes always are 2-nodes (1 value). The node may be
// a leaf, or has 2 children.
Node(T x) {
vals.add(x);
}
Node(T x, Node<T> left, Node<T> right) {
vals.add(x);
children.add(left);
children.add(right);
children.add(null); // hack
}
This is my recursive function to print the nodes:
private boolean iterateChildrenAndPrintPerLevelAndLevelType(int level, String levelType, Node root){
System.out.println("present element: " + root);
if(root.vals.size() == 1 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0));
}else if(root.vals.size() == 2 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0) + "/" + root.vals.get(1));
}
if(root.children.get(0) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "left", (Node) root.children.get(0));
}
if(root.children.get(1) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "middle", (Node) root.children.get(1));
}
if(root.children.get(2) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "right", (Node) root.children.get(2));
}
return true;
}
And here is the output:
present element: [[[a]b[c]]d, [[e]f[g]]h[[i]j, [k]y[z]]]
Level = 0 [root] value = d/h
present element: [[a]b[c]]
Level = 1 [left] value = b
present element: [a]
Level = 2 [left] value = a
(Edit) Here is my main method:
public static void main(String[] args) {
StringTwoThreeTree set = new StringTwoThreeTree();
try{
String line = null;
FileReader fileReader =
new FileReader("C:\\Users\\Redoubt\\IdeaProjects\\23Tree\\src\\resources\\test.dat");
// new FileReader("C:\\Users\\Redoubt\\IdeaProjects\\23Tree\\src\\resources\\a4q1search.txt");
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader =
new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null) {
set.insert(line);
}
// System.out.println("\n\n\n");
String str = set.toString();
// System.out.println(str);
set.print();
}catch (Exception e){
}
}
and the contents of the file test.dat :
a
a
b
c
d
e
f
g
h
i
j
k
y
z
Just for clarity, I'm adding the 2 large classes as well:
StringTwoThree class:
import java.util.List;
public class StringTwoThreeTree extends TwoThreeTree<String> {
#Override
public String toString() {
return super.toString();
}
public void insert(String str){
super.add(str);
}
public void print(){
Node root = super.root;
// System.out.println(root.vals);
// dumpList("",root);
iterateChildrenAndPrintPerLevelAndLevelType(0, "root", root);
super.displayLevelWise();
}
private void dumpList(String string, Node list) {
int i = 0;
for (Object item : list.children) {
if (item instanceof List) {
dumpList(string + i, (Node) item);
} else {
System.out.println(String.format("%s%d %s", string, i, item));
}
++i;
}
}
private boolean iterateChildrenAndPrintPerLevelAndLevelType(int level, String levelType, Node root){
System.out.println("present element: " + root);
if(root.vals.size() == 1 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0));
}else if(root.vals.size() == 2 ){
System.out.println("Level = " + level + " [" + levelType + "] value = " + root.vals.get(0) + "/" + root.vals.get(1));
}
if(root.children.get(0) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "left", (Node) root.children.get(0));
}
if(root.children.get(1) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "middle", (Node) root.children.get(1));
}
if(root.children.get(2) != null){
iterateChildrenAndPrintPerLevelAndLevelType(level+1, "right", (Node) root.children.get(2));
}
return true;
}
}
TwoThreeTree class:
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Queue;
public class TwoThreeTree<T extends Comparable<T>> implements Iterable<T> {
// a Node has 1 (2-Node) or 2 (3-Node) values
// and 2 or 3 children. Values and children are stored
// in ArrayLists. If there are children, that ArrayList
// has a null element at the end, so as to make easier the
// method which adds a new child.
class Node<T extends Comparable<T>> {
List<T> vals = new ArrayList<T>();
List<Node<T>> children = new ArrayList<Node<T>>();
boolean isLeaf() { return children.size() == 0; }
boolean is4Node() { return vals.size() == 3; }
// new Nodes always are 2-nodes (1 value). The node may be
// a leaf, or has 2 children.
Node(T x) {
vals.add(x);
}
Node(T x, Node<T> left, Node<T> right) {
vals.add(x);
children.add(left);
children.add(right);
children.add(null); // hack
}
public String toString() {
String answer = "[";
for (int i=0; i<vals.size(); i++) {
if (i != 0) answer += ", ";
if (children.size() != 0)
answer += children.get(i).toString();
answer += vals.get(i);
}
if (children.size() != 0)
answer += children.get(children.size()-2).toString();
return answer + "]";
}
// used in Iterator
void getVals(List<T> iteratorList) {
for (int i=0; i<vals.size(); i++) {
if (children.size() != 0)
children.get(i).getVals(iteratorList);
iteratorList.add(vals.get(i));
}
if (children.size() != 0)
children.get(children.size()-2).getVals(iteratorList);
}
// recursively adds a new value to a subtree
boolean add(T val) {
if (isLeaf())
return addToLeaf(val);
else return addToInterior(val);
}
// new values are always added to a leaf. The result may be a 4-node leaf.
boolean addToLeaf(T x) {
int cmp;
// size is 1 for a 2-node, or 2 for a 3-node
for (int i = 0; i < vals.size(); i++) {
cmp = x.compareTo(vals.get(i));
if (cmp == 0) return false;
else if (cmp < 0) {
vals.add(i,x);
return true;
}
}
vals.add(x);
return true;
}
// adds a value to a subtree rooted by an interior node. If
// the addition results in one of the children being a 4-node,
// then adjustments are made.
boolean addToInterior(T x) {
int cmp;
// size is 1 for a 2-node, or 2 for a 3-node
for (int i = 0; i <= vals.size(); i++) {
if (i == vals.size()) cmp = -1; // hack because there is no vals[2]
else cmp = x.compareTo(vals.get(i));
if (cmp == 0) return false;
else if (cmp < 0) {
boolean retVal = children.get(i).add(x);
if (children.get(i).is4Node())
childIs4Node(i);
return retVal;
}
}
return false; // unreachable -- just for compiler
}
// the ith child is a 4-node
void childIs4Node(int i) {
Node<T> the4Node = children.get(i);
// move the middle value from the 4-node child up
// to its parent
if (i == 2)
vals.add(children.get(i).vals.get(1));
else vals.add(i, children.get(i).vals.get(1));
Node<T> newChild1, newChild2;
if (children.get(i).isLeaf()) {
newChild1 = new Node<T>(children.get(i).vals.get(0));
newChild2 = new Node<T>(children.get(i).vals.get(2));
}
else {
newChild1 = new Node<T>(children.get(i).vals.get(0),
children.get(i).children.get(0),
children.get(i).children.get(1));
newChild2 = new Node<T>(children.get(i).vals.get(2),
children.get(i).children.get(2),
children.get(i).children.get(3));
}
children.remove(the4Node);
children.add(i, newChild2);
children.add(i, newChild1);
}
}
Node<T> root;
public TwoThreeTree() {
root = null;
}
// TwoThreeTree add
public boolean add(T val) {
if (root == null) {
root = new Node<T>(val);
return true;
}
else {
boolean isNew = root.add(val);
// if root is a 4-node, split it
if (root.vals.size() == 3) {
Node<T> left, right;
if (root.isLeaf()) {
left = new Node<T>(root.vals.get(0));
right = new Node<T>(root.vals.get(2));
}
else {
left = new Node<T>(root.vals.get(0),
root.children.get(0),
root.children.get(1));
right = new Node<T>(root.vals.get(2),
root.children.get(2),
root.children.get(3));
}
root = new Node<T>(root.vals.get(1), left, right);
}
return isNew;
}
}
// this method creates a list containing all of the values in
// the tree and returns that list's iterator
public Iterator<T> iterator() {
List<T> vals = new ArrayList<T>();
if (root != null) root.getVals(vals);
return vals.iterator();
}
public String toString(){
String result = "[";
for (T item : this
) {
result += item.toString() + ",";
}
result = result.substring(0,result.length()-1);
result += "]";
return result;
}
public void displayLevelWise(){
}
}
Your index is going out of bound in your private boolean iterateChildrenAndPrintPerLevelAndLevelType(int level, String levelType, Node root) method.
I'm trying to write a class into which I can enter words, and a tree of characters will be created from the entered word. The tree can then be checked whether a certain word exists in it. My issue is that I can only get it to save one character from any word - if a word has more than one character, only the first one is saved (I'm pretty sure the contains method is right). This is my code, something is evidently wrong with it however I can't tell what:
public class Dictionary {
private Map<Character, DictionaryTree> children = new LinkedHashMap<>();
private boolean endOfWord;
DictionaryTree() {
endOfWord = false;
}
void insert(String word) {
if (!contains(word)) {
DictionaryTree newDictionaryTree = new DictionaryTree();
if (word.length() > 1) {
newDictionaryTree.insert(word.substring(1, word.length()));
} else if (word.length() == 1) {
newDictionaryTree.endOfWord = true;
}
children.put(word.charAt(0), newDictionaryTree);
}
}
boolean contains(String word) {
if (word.length() > 0) {
// Check if first letter is a child node
if (children.containsKey(word.charAt(0))) {
if (word.length() > 1) {
DictionaryTree extractedDictionaryTree = children.get(word.charAt(0));
extractedDictionaryTree.contains(word.substring(1, word.length()));
}
// If only one character left, check if end of word
else if (children.get(word.charAt(0)).endOfWord == true) {
return true;
} else {
return false;
}
}
return false;
}
return false;
}
}
Any help would be much appreciated.
As per your requirement you want to search a word, if it exists or not.
You will achieve it with LinkedHashmap but you try with the Trie data structure. Which provides the efficient way to insert as well as search the String or any data in an efficient way.
Source code is referenced from GeeksForGeeks
root
/ \ \
t a b
| | |
h n y
| | \ |
e s y e
/ | |
i r w
| | |
r e e
|
r
Implementation:
// Java implementation of search and insert operations
// on Trie
public class Trie {
// Alphabet size (# of symbols)
static final int ALPHABET_SIZE = 26;
// trie node
static class TrieNode
{
TrieNode[] children = new TrieNode[ALPHABET_SIZE];
// isEndOfWord is true if the node represents
// end of a word
boolean isEndOfWord;
TrieNode(){
isEndOfWord = false;
for (int i = 0; i < ALPHABET_SIZE; i++)
children[i] = null;
}
};
static TrieNode root;
// If not present, inserts key into trie
// If the key is prefix of trie node,
// just marks leaf node
static void insert(String key)
{
int level;
int length = key.length();
int index;
TrieNode pCrawl = root;
for (level = 0; level < length; level++)
{
index = key.charAt(level) - 'a';
if (pCrawl.children[index] == null)
pCrawl.children[index] = new TrieNode();
pCrawl = pCrawl.children[index];
}
// mark last node as leaf
pCrawl.isEndOfWord = true;
}
// Returns true if key presents in trie, else false
static boolean search(String key)
{
int level;
int length = key.length();
int index;
TrieNode pCrawl = root;
for (level = 0; level < length; level++)
{
index = key.charAt(level) - 'a';
if (pCrawl.children[index] == null)
return false;
pCrawl = pCrawl.children[index];
}
return (pCrawl != null && pCrawl.isEndOfWord);
}
// Driver
public static void main(String args[])
{
// Input keys (use only 'a' through 'z' and lower case)
String keys[] = {"the", "a", "there", "answer", "any",
"by", "bye", "their"};
String output[] = {"Not present in trie", "Present in trie"};
root = new TrieNode();
// Construct trie
int i;
for (i = 0; i < keys.length ; i++)
insert(keys[i]);
// Search for different keys
if(search("the") == true)
System.out.println("the --- " + output[1]);
else System.out.println("the --- " + output[0]);
if(search("these") == true)
System.out.println("these --- " + output[1]);
else System.out.println("these --- " + output[0]);
if(search("their") == true)
System.out.println("their --- " + output[1]);
else System.out.println("their --- " + output[0]);
if(search("thaw") == true)
System.out.println("thaw --- " + output[1]);
else System.out.println("thaw --- " + output[0]);
}
}
Hope it helps!!!
I am trying to implement the insert method of the Patricia Trie data structure and I am trying to handle this case:
first string: abaxyzalexsky,
second string: abaxyzalex,
third string: abaxyz,
fourth string: aba
I want to mark the trie as the following aba-xyz-alex-sky after inserting the fourth string, but I don't know how can I get it work.
How can I mark the words in the trie in the case above?
public void insert(String s) {
if (nodeRoot == null) {
nodeRoot = new TrieNode(s);
nodeRoot.isWord = true;
} else {
insert(nodeRoot, s);
}
}
private void insert(TrieNode node, String s) {
int len1 = node.edge.length();
int len2 = s.length();
int len = Math.min(len1, len2);
ArrayList<TrieNode> nextNode = node.getNext();
for (int index = 0; index < len; index++) {
if (s.charAt(index) != node.edge.charAt(index)) {
// In case the both words have common substrings and after the
// common substrings the words are split. For example abad, abac
} else if (index == (s.length() - 1)
|| index == (node.edge.length() - 1)) {
// In case the node just needs one path since one word is
// substring of the other.
// For example (aba and abac)
if (len1 > len2) {
// node edge string is longer than the inserted one. For example (abac
// and aba).
String samesubString = node.edge.substring(0, index + 1);
String different = node.edge.substring(index + 1);
node.edge = samesubString;
if (node.getNext() != null && !node.getNext().isEmpty()) {
for (TrieNode subword : node.getNext()) {
//I am here when I insert the third string. The code below retrives wrong data structure.
TrieNode node1 = new TrieNode(different);
node1.isWord = true;
node1.next.add(subword);
node.next.add(node1);
}
} else {
TrieNode leaf = new TrieNode(different);
leaf.isWord = true;
node.next.add(leaf);
for (TrieNode subword : node.getNext()) {
System.out.println(node.getEdge() + "---"
+ subword.getEdge());
}
}
} else {
// new inserted string value is longer. For example (aba
// and abac).
}
} else {
System.out.println("The strings are the same - " + index);
}
}
}
NodeTrie class
package patriciaTrie;
import java.util.ArrayList;
public class TrieNode {
ArrayList<TrieNode> next = new ArrayList<TrieNode>();
String edge;
boolean isWord;
TrieNode(String edge){
this.edge = edge;
}
public ArrayList<TrieNode> getNext() {
return next;
}
public void setNext(ArrayList<TrieNode> next) {
this.next = next;
}
public String getEdge() {
return edge;
}
public void setEdge(String edge) {
this.edge = edge;
}
}
I have to implement the T9 Dictionary .
Essentially, when I am pressing any of the 9 keys, it should show me
the top 5 words that can be started with that combination of keys.
If I type '46', it can give 'hotel' or 'good' depending on whether I
intended 'g' or 'h' when I pressed 4.
The priority is based on which words are relatively popular - you can
use, say, the first 5000 words from the top 100 000 words.
The code I am doing is:
Import
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
T9Dict class
public class T9Dict {
private static final Runtime s_runtime = Runtime.getRuntime();
public static void main(String[] args) throws Exception {
runGC();
long heap1 = usedMemory();
long start = new Date().getTime();
Trie trie = Trie.getInstance();
System.out.println("Creating Dictionary");
File f = new File("C:\\Users\\hp1\\Desktop\\100kfound.txt");
BufferedReader br = new BufferedReader(new FileReader(f));
String s = br.readLine();
int i = 0;
do {
i++;
trie.add(s);
s = br.readLine();
} while (s != null);
br.close();
long end = new Date().getTime();
long time = (end - start);
System.out.println("Loaded Dictionary with " + i + " words in " + time
+ " msec");
// runGC();
long heap2 = usedMemory(); // take an "after" heap snapshot:
System.out.println("Memory used = " + (heap2 - heap1));
String pattern = "4663";
start = new Date().getTime();
String word = trie.getWord(pattern);
end = new Date().getTime();
time = (end - start);
System.out.println("Found word : " + word + " in " + time + " msec");
}
private static void runGC() throws Exception {
// for whatever reason it helps to call Runtime.gc()
// using several method calls:
for (int r = 0; r < 4; ++r) {
_runGC();
}
}
private static void _runGC() throws Exception {
long usedMem1 = usedMemory();
long usedMem2 = Long.MAX_VALUE;
for (int i = 0; (usedMem1 < usedMem2) && (i < 1000); ++i) {
s_runtime.runFinalization();
s_runtime.gc();
Thread.currentThread().yield();
usedMem2 = usedMem1;
usedMem1 = usedMemory();
}
}
private static long usedMemory() {
return s_runtime.totalMemory() - s_runtime.freeMemory();
}
}
Trie class
class Trie {
private static final String regex = "[a-zA-Z]*";
private static Trie instance = null;
Node root = null;
Map<Character, Integer> map = new HashMap<Character, Integer>();
private Trie() {
map.put('a', 2);
map.put('b', 2);
map.put('c', 2);
map.put('d', 3);
map.put('e', 3);
map.put('f', 3);
map.put('g', 4);
map.put('h', 4);
map.put('i', 4);
map.put('j', 5);
map.put('k', 5);
map.put('l', 5);
map.put('m', 6);
map.put('n', 6);
map.put('o', 6);
map.put('p', 7);
map.put('q', 7);
map.put('r', 7);
map.put('s', 7);
map.put('t', 8);
map.put('u', 8);
map.put('v', 8);
map.put('w', 9);
map.put('x', 9);
map.put('y', 9);
map.put('z', 9);
}
private int getVal(char c) {
return map.get(c);
}
public static Trie getInstance() {
if (instance == null) {
synchronized (Trie.class) {
instance = new Trie();
}
}
return instance;
}
public String getWord(String pattern) {
String s = null;
Node node = root;
int i = 0;
int num = 0;
while (i < pattern.length()) {
num = pattern.charAt(i) - '0';
if (num == node.val) {
i++;
if (i == pattern.length()) {
s = node.list.get(0);
}
node = node.middle;
} else if (num < node.val) {
if (i == pattern.length()) {
s = node.list.get(0);
}
node = node.left;
} else {
if (i == pattern.length()) {
s = node.list.get(0);
}
node = node.right;
}
}
return s;
}
public void add(String s) {
if (s.length() > 0) {
s = s.toLowerCase();
System.out.println("Adding : " + s);
if (root == null) {
root = new Node(this.getVal(s.charAt(0)));
Node node = root;
Node temp = null;
for (int i = 1; i < s.length(); i++) {
temp = new Node(getVal(s.charAt(i)));
node.middle = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
}
}
} else {
Node node = root;
int i = 0;
Node temp = null;
int val = 0;
while (i < s.length()) {
val = getVal(s.charAt(i));
if (node.val == val) {
if (i == s.length() - 1) {
node.set(s);
i++;
} else {
i++;
if (node.middle == null) {
while (i < s.length()) {
val = getVal(s.charAt(i));
temp = new Node(val);
node.middle = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
}
i++;
}
} else {
node = node.middle;
}
}
} else if (val < node.val) {
if (node.left == null) {
temp = new Node(val);
node.left = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
} else {
i++;
while (i < s.length()) {
val = getVal(s.charAt(i));
temp = new Node(val);
node.middle = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
}
i++;
}
}
} else {
node = node.left;
}
} else {
if (node.right == null) {
temp = new Node(val);
node.right = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
} else {
i++;
while (i < s.length()) {
val = getVal(s.charAt(i));
temp = new Node(val);
node.middle = temp;
node = temp;
if (i == s.length() - 1) {
temp.set(s);
}
i++;
}
}
} else {
node = node.right;
}
}
}
}
}
}
}
Node class
class Node {
int val;
Node left;
Node middle;
Node right;
List<String> list = new LinkedList<String>();
public Node(int val) {
this.val = val;
}
public void set(String s) {
list.add(s);
}
public String toString() {
return String.valueOf(val);
}
}
This code is giving nullpointerexception when adding to Trie
I cannot find the solution please help
1 - You File doesn't contains characters. It is binary so you should use FileInputStream object to read it.
2 - In reading file and adding string in your Trie you should verify that this string is not null, otherwise it can throws a NullPointerException. You can run your file like this:
When I run this I find that the exception occurs on this line:
root = new Node(this.getVal(s.charAt(0)));
Let's unroll this, you're passing the first character of the "word" (ie the String, s) to the getVal(), and this in turn will return an int if, and only if, that character is a lowercase letter, a-z.
When I run the file the "word" is 6724 yahoo - this is the first line of the dictionary text file you linked to. There is nothing in your code to clean up this line to get to the actual word itself, instead you are facing a series of spaces and then a number.
So the reason it fails is because you're effectively going this.getVal(" "). If you call map.get() and the key doesn't exist it'll return null (as described in the Map documentation).
One simple way of getting to the word itself and not the whitespace or frequency number is to first process the string:
s = s.trim(); // removes all leading and trailing whitespace
String word = s.substring(s.indexOf(" ")+1); // extract just the word after the space
And then you can pass the first character of word:
root = new Node(this.getVal(word.charAt(0)));
I am trying to complete an assignment where I need to write a Java program to take a string from the command line, and implement it as a Binary Tree in a specific order, then get the depth of the binary tree.
For example: "((3(4))7((5)9))"
would be entered as a tree with 7 as the root, 3 and 9 as the children, and 4 as a right child of 3, and 5 as a left child of 9.
My code is below.. The problem I am having is that, because I am basing my checks off of finding a right bracket, I am unsure how to get the elements correctly when they are not directly preceding the brackets, such as the 3 in the above string. Any direction would be greatly appreciated..
class Node {
int value;
Node left, right;
}
class BST {
public Node root;
// Add Node to Tree
public void add(int n) {
if (root == null) {
root = new Node( );
root.value = n;
}
else {
Node marker = root;
while (true) {
if (n < marker.value) {
if (marker.left == null) {
marker.left = new Node( );
marker.left.value = n;
break;
} else {
marker = marker.left;
}
} else {
if (marker.right == null) {
marker.right = new Node( );
marker.right.value = n;
break;
} else {
marker = marker.right;
}
}
}
}
} // End ADD
//Find Height of Tree
public int height(Node t) {
if (t.left == null && t.right == null) return 0;
if (t.left == null) return 1 + height(t.right);
if (t.right == null) return 1 + height(t.left);
return 1 + Math.max(height(t.left), height(t.right));
} // End HEIGHT
// Check if string contains an integer
public static boolean isInt(String s) {
try {
Integer.parseInt(s);
}
catch(NumberFormatException e) {
return false;
}
return true;
} // End ISINT
public int elementCount(String[] a) {
int count = 0;
for (int i = 0; i < a.length; i++) {
if (isInt(a[i])) count++;
}
return count;
}
} // End BST Class
public class Depth {
public static void main(String[] args) {
String[] a = args[0].split(" ");
BST tree = new BST();
int[] bcount = new int[10];
int[] elements = new int[10];
int x = 0, bracketcount = 0;
// Display entered string
System.out.print("Entered Format: ");
for (int j=0; j < a.length; j++) {
System.out.print(a[j]);
}
for (int i=0; i < a.length; i++) {
char c = a[i].charAt(0);
switch (c)
{
case '(':
bracketcount++;
break;
case ')':
if (isInt(a[i-1])) {
bcount[x] = bracketcount--;
elements[x++] = Integer.parseInt(a[i-1]);
}
break;
case '1':
case '7':
default : // Illegal character
if ( (a[i-1].charAt(0) == ')') && (a[i+1].charAt(0) == '(') ) {
bcount[x] = bracketcount;
elements[x++] = Integer.parseInt(a[i]);
}
break;
}
}
System.out.println("\nTotal elements: " + tree.elementCount(a));
// Display BracketCounts
for (int w = 0; w < x; w++) {
System.out.print(bcount[w] + " ");
}
System.out.println(" ");
// Display Elements Array
for (int w = 0; w < x; w++) {
System.out.print(elements[w] + " ");
}
System.out.println("\nDepth: " + tree.height(tree.root));
// Build the tree
for (int y = 0; y < x-1; y++) {
for (int z = 1; z < tree.height(tree.root); z++) {
if (bcount[y] == z) {
tree.add(elements[y]);
}
}
}
} // End Main Function
public static boolean isInt(String s) {
try {
Integer.parseInt(s);
}
catch(NumberFormatException e) {
return false;
}
return true;
}
} // End Depth Class
I would do a couple of statements to get access to a tree with that kind of shape:
For input string : input= "((3(4))7((5)9))"
You could do :
public class Trial {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String input = "((3(4))7((5)9))";
String easier = input.replaceAll("\\(\\(", "");
String evenEasier = easier.replaceAll("\\)\\)", "");
System.out.println(evenEasier);
int firstVal = Integer.parseInt(evenEasier.substring(0, 1));
int firstBracketVal = Integer.parseInt(evenEasier.substring(2, 3));
int middleVal = Integer.parseInt(evenEasier.substring(3, 4));
int secondBracketVal = Integer.parseInt(evenEasier.substring(4,5));
int lastVal = Integer.parseInt(evenEasier.substring(6));
System.out.println("First Val:"+firstVal);
System.out.println("First bracket Val:"+firstBracketVal);
System.out.println("Middle Val:"+middleVal);
System.out.println("Second Bracket Val:"+secondBracketVal);
System.out.println("Last Val:"+lastVal);
}
}
This however would only ever work for entries in that specific format, if that were to change, or the length of the input goes up - this would work a bit or break.....If you need to be able to handle more complicated trees as input in this format a bit more thought would be needed on how to best handle and convert into your internal format for processing.
pseudocode:
function getNode(Node)
get one char;
if (the char is "(")
getNode(Node.left);
get one char;
end if;
Node.value = Integer(the char);
get one char;
if (the char is "(")
getNode(Node.right);
get one char;
end if;
//Now the char is ")" and useless.
end function
Before calling this function, you should get a "(" first.
In this method, the framwork of a Node in string is "[leftchild or NULL] value [rightchild or NULL])".
"("is not belong to the Node, but ")" is.