[Mulgara-svn] r749 - projects/xa2/object-pool/scratch

andrae at mulgara.org andrae at mulgara.org
Wed Apr 9 09:13:02 UTC 2008


Author: andrae
Date: 2008-04-09 02:12:59 -0700 (Wed, 09 Apr 2008)
New Revision: 749

Added:
   projects/xa2/object-pool/scratch/TrieTest.java
Log:
More experimenting with Tries.



Added: projects/xa2/object-pool/scratch/TrieTest.java
===================================================================
--- projects/xa2/object-pool/scratch/TrieTest.java	                        (rev 0)
+++ projects/xa2/object-pool/scratch/TrieTest.java	2008-04-09 09:12:59 UTC (rev 749)
@@ -0,0 +1,173 @@
+/*
+ * Copyright Topaz Foundation 2008
+ * Author Andrae Muys
+ * Date 9th April 2008
+ */
+
+/**
+ * Simple test class to help crystalise my thinking on tries.
+ */
+
+public class TrieTest {
+  public static class TrieNode {
+    int type;
+    TrieLeaf least;
+
+    public TrieNode() {
+      type = this.getClass().identityHashCode();
+    }
+  }
+
+  public static class TrieBranch extends TrieNode {
+    public static final int TYPE = TrieBranch.class.identityHashCode();
+
+    int offset;
+    Map<char, TrieNode> children;
+
+    public TrieBranch(String str, long id) {
+      super();
+      this.offset = str.length;
+      this.children = new HashMap<char, TrieNode>();
+      this.least = new TrieLeaf(str, id);
+      this.children.put(null, this.least);
+    }
+
+    public TrieBranch(String lhs, long lhsId, String rhs, long rhsId) {
+      this(lhs, new TrieLeaf(lhs, lhsId), rhs, new TrieLeaf(rhs, rhsId));
+    }
+
+    public TrieBranch(String lhs, TrieNode lhsNode, String rhs, TrieNode rhsNode) {
+      super();
+      assert lhs != null && lhs.length > 0;
+      assert rhs != null && rhs.length > 0;
+
+      children = new HashMap<char, TrieNode>();
+
+      int i = 0;
+      while (i < lhs.length && i < rhs.length) {
+        if (lhs[i] != rhs[i]) {
+          offset = i;
+          children.put(lhs[i], lhsNode);
+          children.put(rhs[i], rhsNode);
+
+          least = lhs[i] < rhs[i] ? lhsNode.least : rhsNode.least;
+
+          return; // Escape here.
+        }
+        i++;
+      }
+
+      assert lhs.length != rhs.length;  // Strings can't be equal.
+
+      // If we reach this point one of the strings is a prefix of the other.
+      if (i < lhs.length) {
+        children.put(lhs[i], lhsNode);
+        children.put(null, rhsNode);
+        least = rhsNode.least;
+      } else {
+        children.put(null, lhsNode);
+        children.put(rhs[i], rhsNode);
+        least = lhsNode.least;
+      }
+    }
+
+    public insert(String str, long id) {
+      return insert(new TrieLeaf(str, id));
+    }
+
+    private insert(TrieLeaf node) {
+      if (!least.value.regionMatches(0, node.least.value, 0, offset - 1)) {
+        return REPLACE;
+      } else {
+        // new node matches the lcp of this node.
+        TrieNode child;
+        if (node.least.value.length == offset) {
+          // new node is expected to terminate here.
+          child = children.get(null);
+        } else {
+          // new node is expected to terminate in one of this nodes children.
+          child = children.get(node.least.value[offset]);
+        }
+
+        if (child == null) {
+          // this is the first node to be inserted on this branching value.
+          children.put(node.least.value[offset], node);
+          return SUCCESS;
+        } else {
+          // there is an existing child node branching on this branching value.
+          switch (child.insert(node, id)) {
+            case SUCCESS: return SUCCESS;
+            case DUPLICATE: return DUPLICATE;
+            case REPLACE:
+              // as every child node shares a common lcp, any child will suffice when preparing the new
+              // lcp/offset of the new node.  The least node is only required as the new parent's least node
+              // will be the smallest of the inserted node and this node's least node.
+              children.put(node.least.value[offset],
+                  new TrieBranch(child, child.least.value, node, node.least.value));
+          }
+        }
+      }
+    }
+
+    public long lookup(String str) throws NotFound {
+      if (!least.value.regionMatches(0, node.least.value, 0, offset - 1)) {
+        throw new NotFound();
+      } else {
+        // new node matches the lcp of this node.
+        TrieNode child;
+        if (node.least.value.length == offset) {
+          // new node is expected to terminate here.
+          child = children.get(null);
+          if (child != null) {
+            switch (child.type) {
+              case TrieLeaf.TYPE: return ((TrieLeaf)child).id;
+              case TrieBranch.TYPE: throw new IllegalStateException("Trie entry terminated in a branch");
+              default: throw new IllegalStateException("Unknown trie node type");
+            }
+          } else {
+            throw NotFound();
+          }
+        } else {
+          // new node is expected to terminate in one of this nodes children.
+          child = children.get(node.least.value[offset]);
+          if (child != null) {
+            switch (child.type) {
+              case TrieLeaf.TYPE: return ((TrieLeaf)child).id;
+              case TrieBranch.TYPE: return ((TrieBranch)child).lookup(str);
+              default: throw new IllegalStateException("Unknown trie node type");
+            }
+          } else {
+            throw NotFound();
+          }
+        }
+      }
+    }
+  }
+
+
+  public static class TrieLeaf {
+    static final int TYPE = TrieBranch.class.identityHashCode();
+
+    final String value;
+    final long id;
+
+    TrieLeaf(String value, long id) {
+      super();
+      this.value = value;
+      this.id = id;
+      this.least = this;
+    }
+
+    public insert(TrieNode node, long id) {
+      switch (node.type) {
+        case TrieLeaf.TYPE:
+          assert value.equals(node.least.value);
+          return DUPLICATE;
+        case TrieBranch.TYPE:
+          return REPLACE;
+        default:
+          throw new IllegalStateException("Attempt to insert unknown node-type into leaf");
+      }
+    }
+  }
+}




More information about the Mulgara-svn mailing list