Java Code Geeks

Sunday, January 25, 2009

Trie in Java

Trie is a good datastucture, details can be found here - http://en.wikipedia.org/wiki/Trie . I came across Trie while performing "Prefix" based searching. Have you ever Wondered what Data Structure is used behind the Mobile SMSes ? When we type SMS, it finishes the words or proposes what could be the end of the word. They are usually done by Trie or data structures like Trie.
Trie consumes less space so they are hot favourite data structures on PDAs or devices with less memory. Searching of a string in Trie takes around O(m) where m = length of the key. Compare it with Binary Tree which is O(logn) where n = number of elements in the tree. For a dictionary, this n could be real large.

Here is a simple implimentation of the Trie..
One class is called Node class which holds the Key and the value.



  1. public class Node {


  2. private char key;

  3. private String value;

  4. private List children;

  5. private boolean isTerminal;

  6. public boolean isTerminal() {

  7. return isTerminal;

  8. }

  9. public void setTerminal(boolean isTerminal) {

  10. this.isTerminal = isTerminal;

  11. }

  12. public Node(char key,String value)

  13. {

  14. this(key,value,new ArrayList());

  15. }

  16. public Node(char key, String value, List children) {

  17. super();

  18. this.key = key;

  19. this.value = value;

  20. this.children = children;

  21. }


  22. public char getKey() {

  23. return key;

  24. }

  25. public void setKey(char key) {

  26. this.key = key;

  27. }

  28. public String getValue() {

  29. return value;

  30. }

  31. public void setValue(String value) {

  32. this.value = value;

  33. }

  34. public List getChildren() {

  35. return children;

  36. }

  37. public void setChildren(List children) {

  38. this.children = children;

  39. }


  40. public void addChildren(Node child)

  41. {

  42. this.children.add(child);

  43. }






}

And the Main Trie class which builds the tree and finds any key...


package com.ds.trie;


  1. import java.io.BufferedReader;

  2. import java.io.File;

  3. import java.io.FileNotFoundException;

  4. import java.io.FileReader;

  5. import java.io.IOException;

  6. import java.util.ArrayList;

  7. import java.util.LinkedList;

  8. import java.util.List;

  9. import java.util.Queue;


  10. public class Trie {


  11. private Node root;

  12. private File fname;


  13. public Trie (String filename)

  14. {

  15. this.root = new Node('r',"root");

  16. this.fname = new File(filename);

  17. }


  18. public void buildTrie()

  19. {

  20. try {


  21. if (!fname.isFile())

  22. throw new FileNotFoundException("");

  23. BufferedReader f = new BufferedReader(new FileReader(fname));

  24. String key;

  25. try {

  26. while ((key = f.readLine()) != null)

  27. {

  28. // making value = full name only = key

  29. build(key,root,key);

  30. }

  31. } catch (IOException e) {

  32. // TODO Auto-generated catch block

  33. e.printStackTrace();

  34. }

  35. } catch (FileNotFoundException e) {

  36. // TODO Auto-generated catch block

  37. e.printStackTrace();

  38. }

  39. }


  40. // key = shamik

  41. private void build(String key,Node root,String value) {

  42. // TODO Auto-generated method stub

  43. char c = key.charAt(0); // c = s

  44. String tail = null;

  45. if (key.length() > 1)

  46. tail = key.substring(1); // hamik

  47. Node resultNode = findKeyinChildren(root,c); // find 's' in the children

  48. if (resultNode == null)

  49. {

  50. // this is a new key

  51. Node newNode = new Node(c,value);

  52. if (tail == null)

  53. newNode.setTerminal(true);

  54. else

  55. newNode.setTerminal(false);


  56. root.addChildren(newNode);

  57. if (tail == null)

  58. {

  59. return;

  60. }

  61. else

  62. build(tail,newNode,value);

  63. }

  64. else // got the key - s

  65. {

  66. if (tail == null)

  67. return;

  68. build (tail,resultNode,value);

  69. }

  70. }


  71. private Node findKeyinChildren(Node root, char c) {

  72. // TODO Auto-generated method stub

  73. List list = root.getChildren();

  74. if (list == null || list.size() == 0)

  75. return null;

  76. for (int i=0; i < list.size(); i++)

  77. {

  78. Node oneNode = list.get(i);

  79. if (oneNode.getKey() == c)

  80. return oneNode;

  81. }

  82. return null;

  83. }


  84. public List findKey(String key)

  85. {


  86. String value = null;

  87. List values = new ArrayList();


  88. Node resultNode = findinTrie(key,root);


  89. if (resultNode == null)

  90. {

  91. value = "Not found";

  92. values.add(value);


  93. }

  94. else

  95. {


  96. printTree(resultNode,values);


  97. }

  98. return values;


  99. }


  100. private void printTree(Node resultNode,List values) {

  101. // TODO Auto-generated method stub

  102. List list = resultNode.getChildren();


  103. if (resultNode.isTerminal())

  104. values.add(resultNode.getValue());


  105. if (list.size() == 0)

  106. {


  107. return;


  108. }

  109. else

  110. {

  111. for (int i=0; i<list.size();i++)

  112. {

  113. Node oneNode = list.get(i);

  114. printTree(oneNode,values);

  115. }

  116. }

  117. }


  118. private Node findinTrie(String key, Node root) {

  119. // TODO Auto-generated method stub

  120. // Implementing the Breath First Traversal

  121. char first = key.charAt(0);

  122. String tail = null;

  123. if (key.length() > 1)

  124. tail = key.substring(1);


  125. Node resultNode = this.findKeyinChildren(root, first);

  126. if (resultNode == null)

  127. {

  128. return null;

  129. }

  130. else

  131. {

  132. if (tail == null)

  133. return resultNode;

  134. else

  135. resultNode = findinTrie(tail,resultNode );

  136. }


  137. return resultNode;

  138. }


  139. public static void main(String[] args)

  140. {

  141. if (args.length <= 0)

  142. {

  143. System.out.println("Usage : Trie ");

  144. System.exit(1);

  145. }

  146. Trie trie = new Trie("C:\\test\\dictionary");

  147. trie.buildTrie();

  148. System.out.println("Going to look for " + args[0]);

  149. List vals = trie.findKey(args[0]);

  150. for (int i=0; i<vals.size(); i++)

  151. {

  152. System.out.println("possible value = " + vals.get(i));

  153. }


  154. }


  155. }



Thursday, January 15, 2009

Job Interview Question Part 2

For a tree, find out the largest possible value from the root to the leaf.

private int maxResult = 0;

public int findMaxRoot(Node root)
{
int result = root.getValue();

List nodes = root.getChilds();
if (nodes.size() == 0)
{

return result;
}
else
{

int maxChildTreeValue = 0;
for (int i=0; i {
//result = root.getValue();
Node oneNode = nodes.get(i);

result = findMaxRoot(oneNode);
if (result > maxChildTreeValue)
maxChildTreeValue = result;


}

result = maxChildTreeValue + root.getValue();

if (result > maxResult)
{
maxResult = result;

}
//maxResult = maxResult + root.getValue();


}
return maxResult;
}

Job interview question Part 1

public static int getCountOfOnes(int n) {
/*
Please implement this method to
return the number of '1's in the binary representation of n
for any integer n, where n > 0

Example: for n=6 the binary representation is '110' and the
number of '1's in that
representation is 2

*/
int count = 0;
int a = 1;

for (int i=1 ; i < 31; i++)
{
int val = n & a ;
if (val > 0 )
count++;
a = a << 1;
}

return count;
}


This is an ideal question to find out whether the developer is aware of bitwise operators ... logic is to perform bitwise and and see the value. If the value if more than 0, then that position contains 1.
Example 6 = 110
Perfor bitwise & with 1, result is 110 & 001 = 0 so there is no 1 at this position
bitwise & with 2 (10), result is 110 & 010 = 010 so there is one 1 at the second positions etc..

Thursday, January 8, 2009

Java Vs C++ an analogy

I think any C++ developer tend to think when they move to Java - what they gained and what they lost. I was thinking about Java Vs C++ in terms of memory management and this thought came to my mind. I would like to describe that - working in C++ as if you are preparing food at home vs working in Java is as if you are having your food at a restaurant.
The difference between java and c++ comes clear if we think of having food at a restaurant vs preparing and having food at home. When we have food at restaurant we do not worry about where from the plates are coming (think of who allocates the memory) and who will wash them after having food (think of who frees the memory). So the good think of working in Java or having food at restaurants is that we are free from some house hold activities which are otherwise boring and error prone.
But the actual strength of preparing food at home is that - we can do anything with the food. It all depends upon us to determine how much salt or pepper we need to use in the food. Compared it with having food at restaurant where we have little control over the ingredients of the food (of course I am not referring to open kitchen style of restaurants).
So C++ might still be stronger than Java as there are more freedom given to the developer as what he wants to do - but the developer should be pretty good in it otherwise go out for dinner :-)