В Java нет прямой замены методов setw и setfill. Однако вы можете создать новый объект, который оборачивает PrintStream и добавляет необходимые отступы, когда вы пишете какой-либо вывод. Например:
import java.io.PrintStream;
import java.util.Arrays;
public class PaddedWriter {
private int width = 0;
private char fillChar = ' ';
private final PrintStream writer;
public PaddedWriter(PrintStream writer) {
this.writer = writer;
}
void setw(int i) {
width = i;
}
void setfill(char c) {
fillChar = c;
}
void write(String str) {
write(str.toCharArray());
}
void write(char[] buf) {
if (buf.length < width) {
char[] pad = new char[width - buf.length];
Arrays.fill( pad, fillChar );
writer.print(pad);
}
writer.print( buf );
setw(0);
}
void write() {
char[] pad = new char[width];
Arrays.fill( pad, fillChar );
writer.print(pad);
setw(0);
}
void endl() {
writer.println();
setw(0);
}
}
Используя класс PaddedWriter, можно переопределить код из http://www.ihas1337code.com/2010/09/how-to-pretty-print-binary-tree.html следующим образом:
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
public class BinaryTree<T> {
final T data;
BinaryTree<T> left;
BinaryTree<T> right;
public BinaryTree(T t) {
data = t;
}
public void setLeft(BinaryTree<T> t) {
left = t;
}
public void setRight(BinaryTree<T> t) {
right = t;
}
public BinaryTree<T> getLeft() {
return left;
}
public BinaryTree<T> getRight() {
return right;
}
@Override
public String toString() {
if (data == null) {
return "null";
} else {
return data.toString();
}
}
// Search for the deepest part of the tree
private static <T>int maxHeight(BinaryTree<T> t) {
if (t == null) return 0;
int leftHeight = maxHeight( t.getLeft() );
int rightHeight = maxHeight( t.getRight() );
return (leftHeight > rightHeight) ? leftHeight+1: rightHeight+1;
}
// Pretty formatting of a binary tree to the output stream
public static <T>void printPretty(BinaryTree<T> tree, int level, int indentSpace, PaddedWriter out) {
int h = maxHeight( tree );
int nodesInThisLevel = 1;
int branchLen = 2*((int)Math.pow( 2.0, h )-1) - (3-level) *(int)Math.pow( 2.0, h-1 );
int nodeSpaceLen = 2+(level+1)*(int)Math.pow(2.0,h);
int startLen = branchLen + (3-level) + indentSpace;
Deque<BinaryTree<T>> nodesQueue = new LinkedList<BinaryTree<T>>();
nodesQueue.offerLast( tree );
for (int r = 1; r < h; r++) {
printBranches( branchLen, nodeSpaceLen, startLen, nodesInThisLevel, nodesQueue, out );
branchLen = branchLen/2 - 1;
nodeSpaceLen = nodeSpaceLen/2 + 1;
startLen = branchLen + (3-level) + indentSpace;
printNodes(branchLen, nodeSpaceLen, startLen, nodesInThisLevel, nodesQueue, out);
for (int i = 0; i < nodesInThisLevel; i++) {
BinaryTree<T> currNode = nodesQueue.pollFirst();
if (currNode!=null) {
nodesQueue.offerLast( currNode.getLeft() );
nodesQueue.offerLast( currNode.getRight() );
} else {
nodesQueue.offerLast( null );
nodesQueue.offerLast( null );
}
}
nodesInThisLevel *= 2;
}
printBranches(branchLen, nodeSpaceLen, startLen, nodesInThisLevel, nodesQueue, out);
printLeaves(indentSpace, level, nodesInThisLevel, nodesQueue, out);
}
private static <T>void printBranches(int branchLen, int nodeSpaceLen, int startLen, int nodesInThisLevel, Deque<BinaryTree<T>> nodesQueue, PaddedWriter out) {
Iterator<BinaryTree<T>> iterator = nodesQueue.iterator();
for (int i = 0; i < nodesInThisLevel/2; i++) {
if (i == 0) {
out.setw(startLen-1);
} else {
out.setw(nodeSpaceLen-2);
}
out.write();
BinaryTree<T> next = iterator.next();
if (next != null) {
out.write( "/" );
} else {
out.write(" ");
}
out.setw(2*branchLen+2);
out.write();
next = iterator.next();
if (next != null) {
out.write( "\\" );
} else {
out.write( " " );
}
}
out.endl();
}
// Print the branches and node (eg, ___10___ )
private static <T>void printNodes(int branchLen, int nodeSpaceLen, int startLen, int nodesInThisLevel, Deque<BinaryTree<T>> nodesQueue, PaddedWriter out) {
Iterator<BinaryTree<T>> iterator = nodesQueue.iterator();
BinaryTree<T> currentNode;
for (int i = 0 ; i < nodesInThisLevel; i++) {
currentNode = iterator.next();
if (i == 0) {
out.setw(startLen );
} else {
out.setw(nodeSpaceLen );
}
out.write();
if (currentNode != null && currentNode.getLeft() != null) {
out.setfill( '_' );
} else {
out.setfill( ' ' );
}
out.setw( branchLen+2 );
if (currentNode != null) {
out.write(currentNode.toString());
} else {
out.write();
}
if (currentNode != null && currentNode.getRight() != null) {
out.setfill( '_' );
} else {
out.setfill( ' ' );
}
out.setw(branchLen);
out.write();
out.setfill(' ');
}
out.endl();
}
// Print the leaves only (just for the bottom row)
private static <T>void printLeaves(int indentSpace, int level, int nodesInThisLevel, Deque<BinaryTree<T>> nodesQueue, PaddedWriter out) {
Iterator<BinaryTree<T>> iterator = nodesQueue.iterator();
BinaryTree<T> currentNode;
for (int i = 0; i < nodesInThisLevel; i++) {
currentNode = iterator.next();
if (i == 0) {
out.setw(indentSpace+2);
} else {
out.setw(2*level+2);
}
if (currentNode !=null) {
out.write(currentNode.toString());
} else {
out.write();
}
}
out.endl();
}
}
Может быть протестировано с этим классом:
public class Tester {
public static void main( String[] args ) {
BinaryTree<Integer> root = new BinaryTree<Integer>(30);
root.setLeft(new BinaryTree<Integer>(20));
root.setRight(new BinaryTree<Integer>(40));
root.getLeft().setLeft(new BinaryTree<Integer>(10));
root.getLeft().setRight(new BinaryTree<Integer>(25));
root.getRight().setLeft(new BinaryTree<Integer>(35));
root.getRight().setRight(new BinaryTree<Integer>(50));
root.getLeft().getLeft().setLeft(new BinaryTree<Integer>(5));
root.getLeft().getLeft().setRight(new BinaryTree<Integer>(15));
root.getLeft().getRight().setRight(new BinaryTree<Integer>(28));
root.getRight().getRight().setLeft(new BinaryTree<Integer>(41));
BinaryTree.printPretty( root, 1, 0, new PaddedWriter( System.out ) );
}
}
При использовании этого кода вы, возможно, захотите принять во внимание то, что ширина узла не учитывается при расчете расстояния. Поэтому, если вы добавите узел, содержащий 123456789, он не будет печататься красиво.