📄 ternarytree.java
字号:
} public int size() { return length; } public Object clone() { TernaryTree t = new TernaryTree(); t.lo = (char[])this.lo.clone(); t.hi = (char[])this.hi.clone(); t.eq = (char[])this.eq.clone(); t.sc = (char[])this.sc.clone(); t.kv = (CharVector)this.kv.clone(); t.root = this.root; t.freenode = this.freenode; t.length = this.length; return t; } /** * Recursively insert the median first and then the median of the * lower and upper halves, and so on in order to get a balanced * tree. The array of keys is assumed to be sorted in ascending * order. */ protected void insertBalanced(String[] k, char[] v, int offset, int n) { int m; if (n < 1) return; m = n >> 1; insert(k[m + offset], v[m + offset]); insertBalanced(k, v, offset, m); insertBalanced(k, v, offset + m + 1, n - m - 1); } /** * Balance the tree for best search performance */ public void balance() { // System.out.print("Before root splitchar = "); System.out.println(sc[root]); int i = 0, n = length; String[] k = new String[n]; char[] v = new char[n]; Iterator iter = new Iterator(); while (iter.hasMoreElements()) { v[i] = iter.getValue(); k[i++] = (String)iter.nextElement(); } init(); insertBalanced(k, v, 0, n); // With uniform letter distribution sc[root] should be around 'm' // System.out.print("After root splitchar = "); System.out.println(sc[root]); } /** * Each node stores a character (splitchar) which is part of * some key(s). In a compressed branch (one that only contain * a single string key) the trailer of the key which is not * already in nodes is stored externally in the kv array. * As items are inserted, key substrings decrease. * Some substrings may completely disappear when the whole * branch is totally decompressed. * The tree is traversed to find the key substrings actually * used. In addition, duplicate substrings are removed using * a map (implemented with a TernaryTree!). * */ public void trimToSize() { // first balance the tree for best performance balance(); // redimension the node arrays redimNodeArrays(freenode); // ok, compact kv array CharVector kx = new CharVector(); kx.alloc(1); TernaryTree map = new TernaryTree(); compact(kx, map, root); kv = kx; kv.trimToSize(); } private void compact(CharVector kx, TernaryTree map, char p) { int k; if (p == 0) return; if (sc[p] == 0xFFFF) { k = map.find(kv.getArray(), lo[p]); if (k < 0) { k = kx.alloc(strlen(kv.getArray(), lo[p]) + 1); strcpy(kx.getArray(), k, kv.getArray(), lo[p]); map.insert(kx.getArray(), k, (char)k); } lo[p] = (char)k; } else { compact(kx, map, lo[p]); if (sc[p] != 0) compact(kx, map, eq[p]); compact(kx, map, hi[p]); } } public Enumeration keys() { return new Iterator(); } public class Iterator implements Enumeration { /** * current node index */ int cur; /** * current key */ String curkey; private class Item implements Cloneable { char parent; char child; public Item() { parent = 0; child = 0; } public Item(char p, char c) { parent = p; child = c; } public Object clone() { return new Item(parent, child); } } /** * Node stack */ Stack ns; /** * key stack implemented with a StringBuffer */ StringBuffer ks; public Iterator() { cur = -1; ns = new Stack(); ks = new StringBuffer(); rewind(); } public void rewind() { ns.removeAllElements(); ks.setLength(0); cur = root; run(); } public Object nextElement() { String res = new String(curkey); cur = up(); run(); return res; } public char getValue() { if (cur >= 0) return eq[cur]; return 0; } public boolean hasMoreElements() { return (cur != -1); } /** * traverse upwards */ private int up() { Item i = new Item(); int res = 0; if (ns.empty()) return -1; if (cur != 0 && sc[cur] == 0) return lo[cur]; boolean climb = true; while (climb) { i = (Item)ns.pop(); i.child++; switch (i.child) { case 1: if (sc[i.parent] != 0) { res = eq[i.parent]; ns.push(i.clone()); ks.append(sc[i.parent]); } else { i.child++; ns.push(i.clone()); res = hi[i.parent]; } climb = false; break; case 2: res = hi[i.parent]; ns.push(i.clone()); if (ks.length() > 0) ks.setLength(ks.length() - 1); // pop climb = false; break; default: if (ns.empty()) return -1; climb = true; break; } } return res; } /** * traverse the tree to find next key */ private int run() { if (cur == -1) return -1; boolean leaf = false; for (; ; ) { // first go down on low branch until leaf or compressed branch while (cur != 0) { if (sc[cur] == 0xFFFF) { leaf = true; break; } ns.push(new Item((char)cur, '\u0000')); if (sc[cur] == 0) { leaf = true; break; } cur = lo[cur]; } if (leaf) break; // nothing found, go up one node and try again cur = up(); if (cur == -1) { return -1; } } // The current node should be a data node and // the key should be in the key stack (at least partially) StringBuffer buf = new StringBuffer(ks.toString()); if (sc[cur] == 0xFFFF) { int p = lo[cur]; while (kv.get(p) != 0) buf.append(kv.get(p++)); } curkey = buf.toString(); return 0; } } public void printStats() { System.out.println("Number of keys = " + Integer.toString(length)); System.out.println("Node count = " + Integer.toString(freenode)); // System.out.println("Array length = " + Integer.toString(eq.length)); System.out.println("Key Array length = " + Integer.toString(kv.length())); /* * for(int i=0; i<kv.length(); i++) * if ( kv.get(i) != 0 ) * System.out.print(kv.get(i)); * else * System.out.println(""); * System.out.println("Keys:"); * for(Enumeration enum = keys(); enum.hasMoreElements(); ) * System.out.println(enum.nextElement()); */ }/* public static void main(String[] args) throws Exception { TernaryTree tt = new TernaryTree(); tt.insert("Carlos", 'C'); tt.insert("Car", 'r'); tt.insert("palos", 'l'); tt.insert("pa", 'p'); tt.trimToSize(); System.out.println((char)tt.find("Car")); System.out.println((char)tt.find("Carlos")); System.out.println((char)tt.find("alto")); tt.printStats(); }*/}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -