樹狀結構打印二叉樹,難點在於確定節點之間的間隙。由於每個節點內容的長度不統一,在此處理方法是:選取每個最長的長度作爲標準,其他的節點用空格符補齊。
對一個高爲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;
}
}
}
}
下面的截圖是運行效果: