文本打印树的结构

树是一种非线性数据结构,将树的结构以图形展示出来有助于理解

在这里插入图片描述

  • 主要步骤
    • 一个树节点
      • da’ta:节点所维护的一个对象
      • children:盛装子节点的容器
      • father:记录父节点
      • NAXSIZE:最大子节点数量,NAXSIZE=2时即二叉树
      • FIXED:节点转字符串时固定大小
    • 字符缓存区
      • 提供树的缓存空间
      • 提供二维坐标访问
    • 树到字符串缓存区的映射
      • 节点与树的相对坐标:
        W(宽度):该节点右边所有叶子节点的数量
        H(高度):相对于根节点的高度
        比如“5”的X为:4 ,为:3
      • 节点到缓存区的映射关系:
        X=W*FIXED+FIXED/2
        Y=H*4-4

代码实现

public class Tree<D>  {
	private List<Tree<D>> children;
	private D  data;
	private int  NAXSIZE=10;
	public  Tree<D>  father;
	public static int FIXED =4;
	public Tree(D data) {
		this.data=data;
	}
	public void add(Tree<D> child) {
		if(this.children==null) {
			this.children=new ArrayList<Tree<D>>();
		}
		if(this.NAXSIZE>this.children.size()) {
			this.children.add(child);
			child.setFather(this);
		}else
			System.out.println("Tree children overflow");
	}
	public void setFather(Tree<D> father) {
		this.father=father;
	}
	public int getUpwardX(Tree<D> root,int x) {
		if(this==root) {
			return x;	
		}
		if(root.children!=null) {
			for(Tree<D> child:root.children) {
				if(!child.isChild(this)) {
					x+=child.getWidth();
				}else {
					return getUpwardX(child,x);
				}
			}
		}
		return 0;	
	}
	public int getDownX() {
		if(this.children!=null&&this.children.size()>1) {
			int x=0;
			for(int i=0;i<this.children.size();i++) {
				if(i==this.children.size()-1) {
					x+=this.children.get(i).getWidth()*FIXED/2;	
				}
				else
					x+=this.children.get(i).getWidth();		
			}
			return x;
		}
		return 0;
	}
	public int getUpwardY(Tree<D> root) {
		if (this==root) {
			return 1;
		}else if(this.father==null) {
			return 1;
		} else
			return 1+this.father.getUpwardY(root);
	}
	public int getHeight() {
		if(this.children==null||this.children.size()==0)
			return 1;
		int maxHeight=0;
		for(Tree<D> child:this.children) {
			int childHeight = child.getHeight();
			maxHeight=maxHeight>childHeight?maxHeight:childHeight;
		}
		return maxHeight+1;
	}
	public int getWidth() {
		if(this.children==null||this.children.size()==0)
			return 1;
		int width=0;
		for(Tree<D> child:this.children) {
			width+=child.getWidth();
		}
		return width;
	}
	public  void show() {
		int height = this.getHeight();
		int width = this.getWidth();
		Buffer buffer=new Buffer(height*4,width*FIXED);
		show(this,buffer,0,0);
		System.out.println(buffer);
	}
	public  void show(Tree<D> root, Buffer buffer ,int x,int y) {
		int upwardX = this.getUpwardX(root,0);
		int downX=this.getDownX();
		int upwardY=this.getUpwardY(root);
		int nodey = 4*upwardY-4;
		int nodex = upwardX*FIXED+downX;
		buffer.replace(nodex,nodey , this.toString());
		if(this!=root){
			link(buffer,nodex+FIXED/2-1,nodey,x,y);
		}
		if(this.children!=null) {
			for(Tree<D> child:this.children) {
				child.show(root,buffer,nodex+FIXED/2-1,nodey);
			}
		}
		
	}
	public void link(Buffer buffer,int cx,int cy,int fx ,int fy) {
		buffer.replace(cx, cy-1, "|");
		buffer.replace(cx, cy-2, "+");
		if(cx<fx) {
			for(int i=cx+1;i<fx;i++) {
				buffer.replace(i, cy-2, "-");
			}
		}else {
			for(int i=cx-1;i>fx;i--) {
				buffer.replace(i, cy-2, "-");
			}
		}
		
		buffer.replace(fx, fy+2, "+");
		buffer.replace(fx, fy+1, "|");
	}
	public boolean isChild(Tree<D> node) {
		if(this==node) {
			return true;
		}else if(this.children!=null) {
			for(Tree<D> child:this.children) {
				if(child.isChild(node)) {
					return true ;
				}
			}
		}
		return false;
	};
	public static String repeatString(String str,int c) {
		String tmp=str;
		while(c>0)
			tmp+=str;
		return tmp;
		//String.join(str,Collections.nCopies(c, "")
	}
	
	public String toString() {
		String str = this.data.toString();
		if(str.length()>FIXED) {
			str=str.substring(0, FIXED);
		}
		int x=FIXED-str.length()+1;
		for(int i=0;i<x/2;i++) {
			str+=" ";
		}
		return String.format("%"+FIXED+"s", str);
	}
}
class Buffer{
	int height;
	int width;
	StringBuilder[] list;
	public Buffer(int height,int width) {
		this.height=height;
		this.width=width;
		list=new StringBuilder[height];
		String line="";
		while(line.length()<width)
			line+=" ";
		for(int h=0;h<height;h++) {
			StringBuilder tmp=new StringBuilder(line);
			list[h]=tmp;
		}
	}
	public void replace(int x, int y, String string) {
		list[y].replace(x, x+string.length(), string);
	}
	public String toString() {
		String tmp="";
		for(StringBuilder line:list) {
			tmp+=line+"\n";
		}
		return tmp;
	}
}

测试

	public static void main(String[] args) {
		Tree<Integer> root=new Tree<Integer>(0);
		Tree<Integer> node1=new Tree<Integer>(1);
		Tree<Integer> node2=new Tree<Integer>(2);
		Tree<Integer> node3=new Tree<Integer>(3);
		Tree<Integer> node4=new Tree<Integer>(4);
		Tree<Integer> node5=new Tree<Integer>(5);
		Tree<Integer> node6=new Tree<Integer>(6);
		Tree<Integer> node7=new Tree<Integer>(7);
		root.add(node1);
		root.add(node2);
		node2.add(node3);
		node2.add(node4);
		node2.add(node5);
		node5.add(node6);
		node5.add(node7);
	}

打印整棵树

		root.show()

在这里插入图片描述

打印子树

		node2.show();

在这里插入图片描述

添加节点

		node1.add(new Tree<Integer>(11));
		node1.add(new Tree<Integer>(12));
		root.show()

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_39464369/article/details/89313883
今日推荐