树状结构打印二叉树,难点在于确定节点之间的间隙。由于每个节点内容的长度不统一,在此处理方法是:选取每个最长的长度作为标准,其他的节点用空格符补齐。
对一个高为h的二叉树,最底层(叶子节点),第一个节点距离起始输出间隙为2^0 —1,节点之间的间隙为2^1—1。倒数第二层,第一个节点距离起始输出间隙为2^1—1,节点之间的间隙为2^2—1。即,对于第k层(从上往下数,根节点为第一次),第一个节点距离起始输出位置为2^(h-k)—1,节点之间的间隙为2^(h-k+1) —1。
在本例中,null**表示叶子节点的left、right节点。在插入节点时,输入null**,在输入节点内容,就可以完成插入操作。在代码中,还额外实现了前、中、后序遍历。
树节点的代码如下:
public class TreeNode {
public String s;
public TreeNode left;
public TreeNode right;
public TreeNode(){
this.s = "null" + Tree.nullNum;
Tree.nullNum++;
left = null;
right = null;
}
}
树的代码如下:
import java.util.ArrayList;
import java.util.List;
public class Tree {
public static int nullNum = 0;
private TreeNode root;
public Tree(){
initTree();
}
public void initTree(){
nullNum = 0;
root = new TreeNode();
}
public String printTree(){
String tree = "";
List<TreeNode> level = new ArrayList<TreeNode>();
List<List<TreeNode>> wholeTree = new ArrayList<List<TreeNode>>();
int maxLength = 0;
level.add(root);
while(level.size() > 0){
wholeTree.add(level);
List<TreeNode> newLevel = new ArrayList<TreeNode>();
for (int i = 0; i < level.size(); i++){
TreeNode node = level.get(i);
if (node.s.length() > maxLength){
maxLength = node.s.length();
}
if (node.left != null && node.right != null){
newLevel.add(node.left);
newLevel.add(node.right);
}
}
level = newLevel;
}
int height = wholeTree.size();
for (int i = 0; i < height; i++){
level = wholeTree.get(i);
int spaceNum = (int) ((Math.pow(2, height - i - 1) - 1) * (maxLength + 1));
for (int j = 0; j < spaceNum; j++){
tree += " ";
}
tree += addSpace(level.get(0).s,maxLength);
spaceNum = (int) ((Math.pow(2, height - i) - 1) * (maxLength + 1));
for (int j = 1; j < level.size(); j++){
for (int k = 0; k < spaceNum; k++){
tree += " ";
}
tree += addSpace(level.get(j).s,maxLength);
}
tree += "\n";
}
System.out.println(tree);
return tree;
}
public String addSpace(String s, int length){
int initLength = s.length();
for(int i = 0; i < (length - initLength) / 2; i++){
s = " " + s;
}
while(s.length() <= length){
s += " ";
}
return s;
}
//插入节点
public boolean insert(String position, String s){
List<TreeNode> list = new ArrayList<TreeNode>();
list.add(root);
return insert(position,s,list);
}
public boolean insert(String position, String s, List<TreeNode> list){
if(list.size() == 0){
return false;
}
List<TreeNode> childList = new ArrayList<TreeNode>();
for(int i = 0; i < list.size(); i++){
TreeNode node = list.get(i);
if (position.equals(node.s)){
if (position.startsWith("null") && node.left == null && node.right == null){
for (int j = 0; j < list.size(); j++){
TreeNode temp = list.get(j);
temp.left = new TreeNode();
temp.right = new TreeNode();
}
}
node.s = s;
return true;
}else{
if (node.left != null){
childList.add(node.left);
}
if (node.right != null){
childList.add(node.right);
}
}
}
return insert(position,s,childList);
}
//前序遍历
public String preOrder(){
return preOrder(root);
}
public String preOrder(TreeNode pivot){
String tree = "";
if (! pivot.s.startsWith("null")){
tree += pivot.s + " " + preOrder(pivot.left) + " " + preOrder(pivot.right) + " ";
}
return tree;
}
//中序遍历
public String inOrder(){
return inOrder(root);
}
public String inOrder(TreeNode pivot){
String tree = "";
if (! pivot.s.startsWith("null")){
tree += inOrder(pivot.left) + " " + pivot.s + " " + inOrder(pivot.right) + " ";
}
return tree;
}
//后序遍历
public String postOrder(){
return postOrder(root);
}
public String postOrder(TreeNode pivot){
String tree = "";
if (! pivot.s.startsWith("null")){
tree += postOrder(pivot.left) + " " + postOrder(pivot.right) + " " + pivot.s + " ";
}
return tree;
}
}
测试类的代码如下
mport java.util.Scanner;
public class Test {
public static void main(String[] args){
Tree tree = new Tree();
Scanner in = new Scanner(System.in);
while(true){
tree.printTree();
System.out.println("请输入需要插入的位置");
String position = in.nextLine().trim().replace("\n", "");
System.out.println("请输入节点内容");
String s = in.nextLine().trim().replace("\n", "");
if(tree.insert(position, s) == false){
System.out.println("你输入的位置不存在...");
break;
}
}
}
}
下面的截图是运行效果: