Display a tree with monospaced font (as in notepad)

808 views Asked by At

Currently I have a program that generates a tree. I used https://stackoverflow.com/a/8948691 to get a string output of the tree. For this, I slightly altered the function in the link: Instead of using System.out.println I rewrote the code to fit my requirements:

public String getStringRepresentation(String prefix, boolean end, int position)
    {
        String retval = prefix + (position != -1? (end ? "└──" : "├──") + " " + position  +(branches==null? "[" + content + "]" : ""):"") + "\r\n";
        if(branches != null)    
        {
            for (int i = 0; i < branches.size() - 1; i++) {
                retval += branches.get(i).getStringRepresentation(prefix + (end ? "    " : "│   "), false,i);
            }
            if (branches.size() >= 1) {
                 retval += branches.get(branches.size() - 1).getStringRepresentation(prefix + (end ?"    " : "│   "), true,branches.size() - 1);
            }
        }
        return retval;   
    }

An example text output would be

├── 0
│   ├── 0[F]
│   └── 1
│       ├── 0[V]
│       └── 1[A]
└── 1
    ├── 0[D]
    └── 1[S]

This String I display with the following:

JTextArea textarea = new JTextArea(infoMessage);
        textarea.setFont(new Font("monospaced", Font.PLAIN, 14));
        JOptionPane.showMessageDialog(null, textarea);

which looks like this:

output of above code

(As you can see, the alignment is not as it should be.)

2

There are 2 answers

0
Stefan On

I found the problem. Apparently monospaced is not the right font. If I use "consolas" (the one my notepad uses), everything is displayed correctly.

0
pps On

Here are the java code that prints the binary tree like below:

     1
    / \
   /   \
  2     \
 / \     3
4   5   / \
       9   \
            8
           / \
          6   7

Code:

package com.dsalgo;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

public class BinaryTreeNicePrint {

 public static void main(String[] args) {
  Node a = new Node(1);
  Node b = new Node(2);
  Node c = new Node(3);
  Node d = new Node(4);
  Node e = new Node(5);
  Node f = new Node(8);
  Node g = new Node(6);
  Node h = new Node(7);
  Node i = new Node(9);
  a.left = b;
  a.right = c;
  b.left = d;
  b.right = e;
  c.left = i;
  c.right = f;
  f.left = g;
  f.right = h;
  nicePrint(a);
 }

 public static void nicePrint(Node root) {
  List< StringPoint > result = getStrings((getWidth(root) + 1) / 2, 0, root);
  TreeMap< Integer, List< StringPoint > > lines = new TreeMap<  >();
  for (StringPoint s : result) {
   if (lines.get(s.y) != null) {
    lines.get(s.y).add(s);
   } else {
    List< StringPoint > l = new ArrayList<  >();
    l.add(s);
    lines.put(s.y, l);
   }
  }
  for (List< StringPoint > l : lines.values()) {
   System.out.println(flatten(l));
  }
 }

 private static String flatten(List< StringPoint > l) {
  int x = 0;
  StringBuilder sb = new StringBuilder();
  for (StringPoint s : l) {
   sb.append(new String(new char[s.x - x]).replace('\0', ' '));
   sb.append(s.value);
   x = sb.length();
  }
  return sb.toString();
 }

 private static int getWidth(Node root) {
  int width = 0;
  if (root.left != null) {
   width += getWidth(root.left);
  }
  if (root.right != null) {
   width += getWidth(root.right);
  }
  width += ("" + root.value).length();
  return width;
 }

 private static List< StringPoint > getStrings(int x, int y, Node root) {
  List< StringPoint > result = new ArrayList< StringPoint >();
  result.add(new StringPoint(x - ("" + root.value).length() / 2, y, ""
    + root.value));
  if (root.left != null) {
   int width = getWidth(root.left);
   int i = 0;
   for (; i <  (width + 1) / 2; ++i)
    result.add(new StringPoint(x - i - 1, y + i + 1, "/"));
   result.addAll(getStrings(x - i - 1, y + i + 1, root.left));
  }
  if (root.right != null) {
   int width = getWidth(root.right);
   int i = 0;
   for (; i <  (width + 1) / 2; ++i)
    result.add(new StringPoint(x + i + 1, y + i + 1, "\\"));
   result.addAll(getStrings(x + i + 1, y + i + 1, root.right));
  }
  return result;
 }

 static class StringPoint {
  Integer x;
  Integer y;
  String value;

  StringPoint(int x, int y, String value) {
   this.x = x;
   this.y = y;
   this.value = value;
  }

  @Override
  public String toString() {
   return "(" + x + "," + y + "," + value + ")";
  }
 }

 static class Node {
  Node left;
  Node right;
  int value;

  public Node(int value) {
   this.value = value;
  }
 }
}