Daily Archives: December 22, 2014

Patricia Tree

In the structure of my PatriciaTree, it has following parameters:
char c, indicate the char the node has.
HashMap<Character, PatriciaTree> children, indicate the children the node has.
String leftString, this a bit difficult to explain. So let me raise an example. If root only has a word “dog”. So the structure would be like:
.root…….
..\………
…d(og)….
But not:
.root…….
..\………
…d……..
….\…….
…..o……
……\…..
…….g….
So, in this case, I use the leftString to store the string after ‘d’, which is ‘og’. And I call the node d(og) string leaf.

is that I define 4 types of nodes:
1. STATE_ROOT, the root the patricia tree.
2. STATE_STRINGLEAF, it is a leaf, and it has left string in it. Like the example I showed above.
3. STATE_LEAF, it is a leaf, and it doesn’t has left string.
For example, the ‘g’ and ‘t’ nodes are both LEAF node, but not string leaf node.
.root………
..\………..
…d……….
….\………
…..o……..
…../.\…….
…g….t…..
4. STATE_MIDDLE, in the above case, the ‘d’ and ‘o’ are middle nodes.

In the following code. it demonstrate how to build a patricia tree, and the method to find if a word exists in a patricia tree.

  1. import java.util.HashMap;
  2. public class PatriciaTree {
  3.     public static final int STATE_ROOT = 0;
  4.     public static final int STATE_LEAF = 1;
  5.     public static final int STATE_STRINGLEAF = 2;
  6.     public static final int STATE_MIDDLE = 3;
  7.     char c;
  8.     HashMap<Character, PatriciaTree> children;
  9.     int state;    //0 is root, 1 is leaf, 2 is leaf with string, 3 is middle
  10.     String leftString;    //if the node is leaf with string, it has a rest word
  11.     PatriciaTree parent;
  12.     //store word into this PatriciaTree, word starts from pos
  13.     public boolean addNode(String word, int pos, PatriciaTree parent){
  14.         if(word==null||pos>=word.length()){
  15.             return false;
  16.         }
  17.         PatriciaTree child;
  18.         if(state==STATE_ROOT||state==STATE_MIDDLE){
  19.             //if it is root, then find if it children have tree with character pos[0]
  20.             child = children.get(word.charAt(pos));
  21.             if(child==null){    //it doesn’t has word.charAt[pos], then create tree under it.
  22.                 child = new PatriciaTree(word, pos, this);
  23.                 children.put(word.charAt(pos), child);
  24.                 return true;
  25.             }
  26.             return child.addNode(word, pos+1, this);    //it has char, then create tree under its child.
  27.         }
  28.         if(state==STATE_LEAF){
  29.             //now it is leaf, and there is still chars, then just change it to a STRINGLEAF
  30.             this.state = STATE_STRINGLEAF;
  31.             this.leftString = word.substring(pos, word.length()-1);
  32.             return true;
  33.         }
  34.         if(state==STATE_STRINGLEAF){
  35.             if(word.charAt(pos)!=leftString.charAt(0)){
  36.                 //1st char of leftString doesn’t match word[pos], so create the tree under it.
  37.                 //And create leftString as its subtree.
  38.                 child = new PatriciaTree(word, pos, this);
  39.                 children.put(word.charAt(pos), child);
  40.                 child = new PatriciaTree(leftString, 0, this);
  41.                 children.put(leftString.charAt(0), child);
  42.                 this.state = STATE_MIDDLE;
  43.                 return true;
  44.             }
  45.             //1st char of leftString match word[pos], so break the stringleaf into middle,
  46.             //and create its child with char of the 1st leftString
  47.             this.state = STATE_MIDDLE;
  48.             child = new PatriciaTree(leftString, 0, this);
  49.             children.put(leftString.charAt(0), child);
  50.             this.leftString = “”;
  51.             child.addNode(word, pos+1, child);
  52.             return true;
  53.         }
  54.         return false;
  55.     }
  56.     public boolean findString(String word, int pos){
  57.         if(pos>=word.length()){
  58.             if(this.state==STATE_MIDDLE){
  59.                 return false;    //is in the middle, is not counted as found.
  60.             }
  61.             if(this.state==STATE_LEAF){
  62.                 return true;    //return true if this is leaf
  63.             }
  64.             return false;
  65.         }
  66.         PatriciaTree child;
  67.         if(this.state==STATE_ROOT||this.state==STATE_MIDDLE){
  68.             child = this.children.get(word.charAt(pos));
  69.             return child==null?false:child.findString(word, pos+1);
  70.         }
  71.         if(this.state==STATE_LEAF){
  72.             return false;    //the word is larger than the leaf string
  73.         }
  74.         if(this.state==STATE_STRINGLEAF){
  75.             String strInWord = word.substring(pos, word.length());
  76.             if(leftString.equals(strInWord)){
  77.                 return true;
  78.             }
  79.         }
  80.         return false;
  81.     }
  82.     public PatriciaTree(){
  83.         this.children = new HashMap<Character, PatriciaTree>();
  84.     }
  85.     public PatriciaTree(String word, int pos, PatriciaTree parent){
  86.         this.c = word.charAt(pos);
  87.         this.parent = parent;
  88.         this.state = STATE_LEAF;
  89.         this.children = new HashMap<Character, PatriciaTree>();
  90.         if(pos<word.length()-1){
  91.             this.state = STATE_STRINGLEAF;
  92.             this.leftString = word.substring(pos+1, word.length());
  93.         }
  94.     }
  95.     public static void main(String[] args) {
  96.         PatriciaTree root = new PatriciaTree();
  97.         root.state = STATE_ROOT;
  98.         String[] words = {“zebra”, “zero”, “dog”, “dot”, “ducks”, “duh”, “ducky”};
  99.         for(int i=0;i<words.length;i++){
  100.             root.addNode(words[i], 0, root);
  101.         }
  102.         System.out.println(root.findString(“dogg”, 0));
  103.     }
  104. }