Advertisement
Guest User

yct

a guest
May 17th, 2009
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.56 KB | None | 0 0
  1.  
  2. public class ASCIITreePrinter {
  3.  
  4.     int MAX_HEIGHT;
  5.     int INFINITY = Integer.MAX_VALUE;
  6.     int lprofile[], rprofile[];
  7.     int print_next;
  8.     StringBuilder sb;
  9.     int gap = 1;
  10.  
  11.     public ASCIITreePrinter(int max_height) {
  12.         MAX_HEIGHT = max_height;
  13.         lprofile = new int[max_height];
  14.         rprofile = new int[max_height];
  15.         sb = new StringBuilder();
  16.     }
  17.    
  18.     void p(Object o) {
  19.         sb.append(o);
  20.     }
  21.    
  22.     public String toString() {
  23.         return sb.toString();
  24.     }
  25.    
  26.     public interface Node {
  27.         Node getLeft();
  28.         Node getRight();
  29.         Object getElement();
  30.     }
  31.  
  32.     //prints ascii tree for given node classure
  33.     void print_ascii_tree(Node t)
  34.     {
  35.       asciinode proot;
  36.       int xmin, i;
  37.       if (t == null) return;
  38.       proot = build_ascii_tree(t);
  39.       compute_edge_lengths(proot);
  40.       for (i=0; i<proot.height && i < MAX_HEIGHT; i++)
  41.       {
  42.         lprofile[i] = INFINITY;
  43.       }
  44.       compute_lprofile(proot, 0, 0);
  45.       xmin = 0;
  46.       for (i = 0; i < proot.height && i < MAX_HEIGHT; i++)
  47.       {
  48.         xmin = Math.min(xmin, lprofile[i]);
  49.       }
  50.       for (i = 0; i < proot.height; i++)
  51.       {
  52.         print_next = 0;
  53.         print_level(proot, -xmin, i);
  54.         p("\n");
  55.       }
  56.       if (proot.height >= MAX_HEIGHT)
  57.       {
  58.         p("(This tree is taller than " + MAX_HEIGHT + ", and may be drawn incorrectly.)\n");
  59.       }
  60.       free_ascii_tree(proot);
  61.     }
  62.  
  63.     //This function prints the given level of the given tree, assuming
  64.     //that the node has the given x cordinate.
  65.     void print_level(asciinode node, int x, int level)
  66.     {
  67.       int i, isleft;
  68.       if (node == null) return;
  69.       isleft = (node.parent_dir == -1 ? 1 : 0);
  70.       if (level == 0)
  71.       {
  72.         for (i=0; i<(x-print_next-((node.lablen-isleft)/2)); i++)
  73.         {
  74.           p(" ");
  75.         }
  76.         print_next += i;
  77.         p(node.label);
  78.         print_next += node.lablen;
  79.       }
  80.       else if (node.edge_length >= level)
  81.       {
  82.         if (node.left != null)
  83.         {
  84.           for (i=0; i<(x-print_next-(level)); i++)
  85.           {
  86.             p(" ");
  87.           }
  88.           print_next += i;
  89.           p("/");
  90.           print_next++;
  91.         }
  92.         if (node.right != null)
  93.         {
  94.           for (i=0; i<(x-print_next+(level)); i++)
  95.           {
  96.             p(" ");
  97.           }
  98.           print_next += i;
  99.           p("\\");
  100.           print_next++;
  101.         }
  102.       }
  103.       else
  104.       {
  105.         print_level(node.left,
  106.                     x-node.edge_length-1,
  107.                     level-node.edge_length-1);
  108.         print_level(node.right,
  109.                     x+node.edge_length+1,
  110.                     level-node.edge_length-1);
  111.       }
  112.     }
  113.      
  114.      
  115.     //This function fills in the edge_length and
  116.     //height fields of the specified tree
  117.     void compute_edge_lengths(asciinode node)
  118.     {
  119.       int h, hmin, i, delta;
  120.       if (node == null) return;
  121.       compute_edge_lengths(node.left);
  122.       compute_edge_lengths(node.right);
  123.      
  124.       // first fill in the edge_length of node
  125.       if (node.right == null && node.left == null)
  126.       {
  127.         node.edge_length = 0;
  128.       }
  129.       else
  130.       {
  131.         if (node.left != null)
  132.         {
  133.           for (i=0; i<node.left.height && i < MAX_HEIGHT; i++)
  134.           {
  135.             rprofile[i] = -INFINITY;
  136.           }
  137.           compute_rprofile(node.left, 0, 0);
  138.           hmin = node.left.height;
  139.         }
  140.         else
  141.         {
  142.           hmin = 0;
  143.         }
  144.         if (node.right != null)
  145.         {
  146.           for (i=0; i<node.right.height && i < MAX_HEIGHT; i++)
  147.           {
  148.             lprofile[i] = INFINITY;
  149.           }
  150.           compute_lprofile(node.right, 0, 0);
  151.           hmin = Math.min(node.right.height, hmin);
  152.         }
  153.         else
  154.         {
  155.           hmin = 0;
  156.         }
  157.         delta = 4;
  158.         for (i=0; i<hmin; i++)
  159.         {
  160.           delta = Math.max(delta, gap + 1 + rprofile[i] - lprofile[i]);
  161.         }
  162.      
  163.         //If the node has two children of height 1, then we allow the
  164.         //two leaves to be within 1, instead of 2
  165.         if (((node.left != null && node.left.height == 1) ||
  166.               (node.right != null && node.right.height == 1))&&delta>4)
  167.         {
  168.           delta--;
  169.         }
  170.      
  171.         node.edge_length = ((delta+1)/2) - 1;
  172.       }
  173.      
  174.       //now fill in the height of node
  175.       h = 1;
  176.       if (node.left != null)
  177.       {
  178.         h = Math.max(node.left.height + node.edge_length + 1, h);
  179.       }
  180.       if (node.right != null)
  181.       {
  182.         h = Math.max(node.right.height + node.edge_length + 1, h);
  183.       }
  184.       node.height = h;
  185.     }
  186.  
  187.     asciinode  build_ascii_tree_recursive(Node t)
  188.     {
  189.       asciinode  node;
  190.      
  191.       if (t == null) return null;
  192.      
  193.       node = new asciinode();
  194.       node.left = build_ascii_tree_recursive(t.getLeft());
  195.       node.right = build_ascii_tree_recursive(t.getRight());
  196.      
  197.       if (node.left != null)
  198.       {
  199.         node.left.parent_dir = -1;
  200.       }
  201.      
  202.       if (node.right != null)
  203.       {
  204.         node.right.parent_dir = 1;
  205.       }
  206.      
  207.       node.label = String.valueOf(t.getElement());
  208.       node.lablen = node.label.length();
  209.      
  210.       return node;
  211.     }
  212.      
  213.      
  214.     //Copy the tree into the ascii node classre
  215.     asciinode  build_ascii_tree(Node t)
  216.     {
  217.       asciinode node;
  218.       if (t == null) return null;
  219.       node = build_ascii_tree_recursive(t);
  220.       node.parent_dir = 0;
  221.       return node;
  222.     }
  223.      
  224.     //Free all the nodes of the given tree
  225.     void free_ascii_tree(asciinode node)
  226.     {
  227.       if (node == null) return;
  228.       free_ascii_tree(node.left);
  229.       free_ascii_tree(node.right);
  230.       //free(node);
  231.     }
  232.      
  233.     //The following function fills in the lprofile array for the given tree.
  234.     //It assumes that the center of the label of the root of this tree
  235.     //is located at a position (x,y).  It assumes that the edge_length
  236.     //fields have been computed for this tree.
  237.     void compute_lprofile(asciinode node, int x, int y)
  238.     {
  239.       int i, isleft;
  240.       if (node == null) return;
  241.       isleft = node.parent_dir == -1 ? 1 : 0;
  242.       lprofile[y] = Math.min(lprofile[y], x-((node.lablen-isleft)/2));
  243.       if (node.left != null)
  244.       {
  245.         for (i=1; i <= node.edge_length && y+i < MAX_HEIGHT; i++)
  246.         {
  247.           lprofile[y+i] = Math.min(lprofile[y+i], x-i);
  248.         }
  249.       }
  250.       compute_lprofile(node.left, x-node.edge_length-1, y+node.edge_length+1);
  251.       compute_lprofile(node.right, x+node.edge_length+1, y+node.edge_length+1);
  252.     }
  253.      
  254.     void compute_rprofile(asciinode node, int x, int y)
  255.     {
  256.       int i, notleft;
  257.       if (node == null) return;
  258.       notleft = (node.parent_dir != -1 ? 1 : 0);
  259.       rprofile[y] = Math.max(rprofile[y], x+((node.lablen-notleft)/2));
  260.       if (node.right != null)
  261.       {
  262.         for (i=1; i <= node.edge_length && y+i < MAX_HEIGHT; i++)
  263.         {
  264.           rprofile[y+i] = Math.max(rprofile[y+i], x+i);
  265.         }
  266.       }
  267.       compute_rprofile(node.left, x-node.edge_length-1, y+node.edge_length+1);
  268.       compute_rprofile(node.right, x+node.edge_length+1, y+node.edge_length+1);
  269.     }
  270.  
  271.     static class asciinode
  272.     {
  273.       asciinode  left,  right;
  274.      
  275.       //length of the edge from this node to its children
  276.       int edge_length;
  277.      
  278.       int height;      
  279.      
  280.       int lablen;
  281.      
  282.       //-1=I am left, 0=I am root, 1=right  
  283.       int parent_dir;  
  284.      
  285.       //max supported unit32 in dec, 10 digits max
  286.       String label;  
  287.     };
  288. }
  289.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement