1 17 18 19 20 package org.apache.fop.hyphenation; 21 22 import java.util.Enumeration ; 23 import java.util.Stack ; 24 import java.io.Serializable ; 25 26 67 68 public class TernaryTree implements Cloneable , Serializable { 69 70 77 78 82 protected char[] lo; 83 84 87 protected char[] hi; 88 89 92 protected char[] eq; 93 94 103 protected char[] sc; 104 105 108 protected CharVector kv; 109 110 protected char root; 111 protected char freenode; 112 protected int length; 114 protected static final int BLOCK_SIZE = 2048; 116 TernaryTree() { 117 init(); 118 } 119 120 protected void init() { 121 root = 0; 122 freenode = 1; 123 length = 0; 124 lo = new char[BLOCK_SIZE]; 125 hi = new char[BLOCK_SIZE]; 126 eq = new char[BLOCK_SIZE]; 127 sc = new char[BLOCK_SIZE]; 128 kv = new CharVector(); 129 } 130 131 139 public void insert(String key, char val) { 140 int len = key.length() 142 + 1; if (freenode + len > eq.length) { 144 redimNodeArrays(eq.length + BLOCK_SIZE); 145 } 146 char strkey[] = new char[len--]; 147 key.getChars(0, len, strkey, 0); 148 strkey[len] = 0; 149 root = insert(root, strkey, 0, val); 150 } 151 152 public void insert(char[] key, int start, char val) { 153 int len = strlen(key) + 1; 154 if (freenode + len > eq.length) { 155 redimNodeArrays(eq.length + BLOCK_SIZE); 156 } 157 root = insert(root, key, start, val); 158 } 159 160 163 private char insert(char p, char[] key, int start, char val) { 164 int len = strlen(key, start); 165 if (p == 0) { 166 p = freenode++; 170 eq[p] = val; length++; 172 hi[p] = 0; 173 if (len > 0) { 174 sc[p] = 0xFFFF; lo[p] = (char)kv.alloc(len 176 + 1); strcpy(kv.getArray(), lo[p], key, start); 178 } else { 179 sc[p] = 0; 180 lo[p] = 0; 181 } 182 return p; 183 } 184 185 if (sc[p] == 0xFFFF) { 186 char pp = freenode++; 190 lo[pp] = lo[p]; eq[pp] = eq[p]; lo[p] = 0; 193 if (len > 0) { 194 sc[p] = kv.get(lo[pp]); 195 eq[p] = pp; 196 lo[pp]++; 197 if (kv.get(lo[pp]) == 0) { 198 lo[pp] = 0; 200 sc[pp] = 0; 201 hi[pp] = 0; 202 } else { 203 sc[pp] = 0xFFFF; 205 } 206 } else { 207 sc[pp] = 0xFFFF; 210 hi[p] = pp; 211 sc[p] = 0; 212 eq[p] = val; 213 length++; 214 return p; 215 } 216 } 217 char s = key[start]; 218 if (s < sc[p]) { 219 lo[p] = insert(lo[p], key, start, val); 220 } else if (s == sc[p]) { 221 if (s != 0) { 222 eq[p] = insert(eq[p], key, start + 1, val); 223 } else { 224 eq[p] = val; 226 } 227 } else { 228 hi[p] = insert(hi[p], key, start, val); 229 } 230 return p; 231 } 232 233 236 public static int strcmp(char[] a, int startA, char[] b, int startB) { 237 for (; a[startA] == b[startB]; startA++, startB++) { 238 if (a[startA] == 0) { 239 return 0; 240 } 241 } 242 return a[startA] - b[startB]; 243 } 244 245 248 public static int strcmp(String str, char[] a, int start) { 249 int i, d, len = str.length(); 250 for (i = 0; i < len; i++) { 251 d = (int)str.charAt(i) - a[start + i]; 252 if (d != 0) { 253 return d; 254 } 255 if (a[start + i] == 0) { 256 return d; 257 } 258 } 259 if (a[start + i] != 0) { 260 return (int)-a[start + i]; 261 } 262 return 0; 263 264 } 265 266 public static void strcpy(char[] dst, int di, char[] src, int si) { 267 while (src[si] != 0) { 268 dst[di++] = src[si++]; 269 } 270 dst[di] = 0; 271 } 272 273 public static int strlen(char[] a, int start) { 274 int len = 0; 275 for (int i = start; i < a.length && a[i] != 0; i++) { 276 len++; 277 } 278 return len; 279 } 280 281 public static int strlen(char[] a) { 282 return strlen(a, 0); 283 } 284 285 public int find(String key) { 286 int len = key.length(); 287 char strkey[] = new char[len + 1]; 288 key.getChars(0, len, strkey, 0); 289 strkey[len] = 0; 290 291 return find(strkey, 0); 292 } 293 294 public int find(char[] key, int start) { 295 int d; 296 char p = root; 297 int i = start; 298 char c; 299 300 while (p != 0) { 301 if (sc[p] == 0xFFFF) { 302 if (strcmp(key, i, kv.getArray(), lo[p]) == 0) { 303 return eq[p]; 304 } else { 305 return -1; 306 } 307 } 308 c = key[i]; 309 d = c - sc[p]; 310 if (d == 0) { 311 if (c == 0) { 312 return eq[p]; 313 } 314 i++; 315 p = eq[p]; 316 } else if (d < 0) { 317 p = lo[p]; 318 } else { 319 p = hi[p]; 320 } 321 } 322 return -1; 323 } 324 325 public boolean knows(String key) { 326 return (find(key) >= 0); 327 } 328 329 private void redimNodeArrays(int newsize) { 331 int len = newsize < lo.length ? newsize : lo.length; 332 char[] na = new char[newsize]; 333 System.arraycopy(lo, 0, na, 0, len); 334 lo = na; 335 na = new char[newsize]; 336 System.arraycopy(hi, 0, na, 0, len); 337 hi = na; 338 na = new char[newsize]; 339 System.arraycopy(eq, 0, na, 0, len); 340 eq = na; 341 na = new char[newsize]; 342 System.arraycopy(sc, 0, na, 0, len); 343 sc = na; 344 } 345 346 public int size() { 347 return length; 348 } 349 350 public Object clone() { 351 TernaryTree t = new TernaryTree(); 352 t.lo = (char[])this.lo.clone(); 353 t.hi = (char[])this.hi.clone(); 354 t.eq = (char[])this.eq.clone(); 355 t.sc = (char[])this.sc.clone(); 356 t.kv = (CharVector)this.kv.clone(); 357 t.root = this.root; 358 t.freenode = this.freenode; 359 t.length = this.length; 360 361 return t; 362 } 363 364 370 protected void insertBalanced(String [] k, char[] v, int offset, int n) { 371 int m; 372 if (n < 1) { 373 return; 374 } 375 m = n >> 1; 376 377 insert(k[m + offset], v[m + offset]); 378 insertBalanced(k, v, offset, m); 379 380 insertBalanced(k, v, offset + m + 1, n - m - 1); 381 } 382 383 384 387 public void balance() { 388 390 int i = 0, n = length; 391 String [] k = new String [n]; 392 char[] v = new char[n]; 393 Iterator iter = new Iterator(); 394 while (iter.hasMoreElements()) { 395 v[i] = iter.getValue(); 396 k[i++] = (String )iter.nextElement(); 397 } 398 init(); 399 insertBalanced(k, v, 0, n); 400 401 } 404 405 418 public void trimToSize() { 419 balance(); 421 422 redimNodeArrays(freenode); 424 425 CharVector kx = new CharVector(); 427 kx.alloc(1); 428 TernaryTree map = new TernaryTree(); 429 compact(kx, map, root); 430 kv = kx; 431 kv.trimToSize(); 432 } 433 434 private void compact(CharVector kx, TernaryTree map, char p) { 435 int k; 436 if (p == 0) { 437 return; 438 } 439 if (sc[p] == 0xFFFF) { 440 k = map.find(kv.getArray(), lo[p]); 441 if (k < 0) { 442 k = kx.alloc(strlen(kv.getArray(), lo[p]) + 1); 443 strcpy(kx.getArray(), k, kv.getArray(), lo[p]); 444 map.insert(kx.getArray(), k, (char)k); 445 } 446 lo[p] = (char)k; 447 } else { 448 compact(kx, map, lo[p]); 449 if (sc[p] != 0) { 450 compact(kx, map, eq[p]); 451 } 452 compact(kx, map, hi[p]); 453 } 454 } 455 456 457 public Enumeration keys() { 458 return new Iterator(); 459 } 460 461 public class Iterator implements Enumeration { 462 463 466 int cur; 467 468 471 String curkey; 472 473 private class Item implements Cloneable { 474 char parent; 475 char child; 476 477 public Item() { 478 parent = 0; 479 child = 0; 480 } 481 482 public Item(char p, char c) { 483 parent = p; 484 child = c; 485 } 486 487 public Object clone() { 488 return new Item(parent, child); 489 } 490 491 } 492 493 496 Stack ns; 497 498 501 StringBuffer ks; 502 503 public Iterator() { 504 cur = -1; 505 ns = new Stack (); 506 ks = new StringBuffer (); 507 rewind(); 508 } 509 510 public void rewind() { 511 ns.removeAllElements(); 512 ks.setLength(0); 513 cur = root; 514 run(); 515 } 516 517 public Object nextElement() { 518 String res = new String (curkey); 519 cur = up(); 520 run(); 521 return res; 522 } 523 524 public char getValue() { 525 if (cur >= 0) { 526 return eq[cur]; 527 } 528 return 0; 529 } 530 531 public boolean hasMoreElements() { 532 return (cur != -1); 533 } 534 535 538 private int up() { 539 Item i = new Item(); 540 int res = 0; 541 542 if (ns.empty()) { 543 return -1; 544 } 545 546 if (cur != 0 && sc[cur] == 0) { 547 return lo[cur]; 548 } 549 550 boolean climb = true; 551 552 while (climb) { 553 i = (Item)ns.pop(); 554 i.child++; 555 switch (i.child) { 556 case 1: 557 if (sc[i.parent] != 0) { 558 res = eq[i.parent]; 559 ns.push(i.clone()); 560 ks.append(sc[i.parent]); 561 } else { 562 i.child++; 563 ns.push(i.clone()); 564 res = hi[i.parent]; 565 } 566 climb = false; 567 break; 568 569 case 2: 570 res = hi[i.parent]; 571 ns.push(i.clone()); 572 if (ks.length() > 0) { 573 ks.setLength(ks.length() - 1); } 575 climb = false; 576 break; 577 578 default: 579 if (ns.empty()) { 580 return -1; 581 } 582 climb = true; 583 break; 584 } 585 } 586 return res; 587 } 588 589 592 private int run() { 593 if (cur == -1) { 594 return -1; 595 } 596 597 boolean leaf = false; 598 while (true) { 599 while (cur != 0) { 601 if (sc[cur] == 0xFFFF) { 602 leaf = true; 603 break; 604 } 605 ns.push(new Item((char)cur, '\u0000')); 606 if (sc[cur] == 0) { 607 leaf = true; 608 break; 609 } 610 cur = lo[cur]; 611 } 612 if (leaf) { 613 break; 614 } 615 cur = up(); 617 if (cur == -1) { 618 return -1; 619 } 620 } 621 StringBuffer buf = new StringBuffer (ks.toString()); 624 if (sc[cur] == 0xFFFF) { 625 int p = lo[cur]; 626 while (kv.get(p) != 0) { 627 buf.append(kv.get(p++)); 628 } 629 } 630 curkey = buf.toString(); 631 return 0; 632 } 633 634 } 635 636 public void printStats() { 637 System.out.println("Number of keys = " + Integer.toString(length)); 638 System.out.println("Node count = " + Integer.toString(freenode)); 639 System.out.println("Key Array length = " 641 + Integer.toString(kv.length())); 642 643 653 654 } 655 656 public static void main(String [] args) throws Exception { 657 TernaryTree tt = new TernaryTree(); 658 tt.insert("Carlos", 'C'); 659 tt.insert("Car", 'r'); 660 tt.insert("palos", 'l'); 661 tt.insert("pa", 'p'); 662 tt.trimToSize(); 663 System.out.println((char)tt.find("Car")); 664 System.out.println((char)tt.find("Carlos")); 665 System.out.println((char)tt.find("alto")); 666 tt.printStats(); 667 } 668 669 } 670 671 | Popular Tags |