日期:2014-05-20  浏览次数:21016 次

层次图算法改造
一个练习题,想了很久头晕了,来请教高人们指点。。
    是这样,本来的图形是以下形状(原图),代码已经有了,下面附上。



想改造为:最下面一层的节点不要横着放,改为竖着放,这样一来数据多的时候就不会显得一行占太多空间(效果图)。。请高人点拨。。

1、 TreeGraphGenerator  
package yfzx.ex01;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class TreeGraphGenerator {
public static void main(String[] a){
TreeGraphGenerator gen=new TreeGraphGenerator();
gen.setDataProvider(new DataProvider(){
String[][] data={
{"000000","国家总局","ROOT"},
{"000012","首都机场办事处","000000"},
{"200000","上海局","000000"},
{"200012","长虹机场办事处","200000"},
{"350000","福建局","000000"},
{"350100","福州局","350000"},
{"350102","马尾办事处","350100"},
{"350112","长乐机场办事处","350100"},
{"352100","宁德局","350000"},
{"352107","三都澳港口","352100"},
{"360000","厦门局","000000"},
{"360011","长崎机场","360000"},
{"362000","漳州局","360000"},
};

public List<Object> getSubNodeData(Object parent) {
List<Object> result=new ArrayList<Object>();
String[] cast=(String[])parent;
String parentId=cast[0];
for(String[] row : data){
if(row[2].equals(parentId)){
result.add(row);
}
}
return result;
}

public List<Object> getTopNodeData() {
return getSubNodeData(new String[]{"ROOT","虚拟根节点",""});
}});
String result= gen.generateHtml();
try {
FileWriter fw=new FileWriter("e:/test_tree.html");
fw.write(result);
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}

public String generateHtml() {
Graph all=new Graph();
for(Object top:dataProvider.getTopNodeData()){
Graph g=new Graph();
g.setDataProvider(dataProvider);
g.setData(top);
g.buildGraph();
all.combine(g);
}

StringBuilder sb=new StringBuilder();
sb.append("<div style='font-size:9pt'>\r\n");
//划横线
for(Line n:all.getVLines()){
if(n.getLen()>0){
sb.append("<div style='position:absolute;border-top:1px solid gray;" +
"left:"+n.getX()+"px;" +
"top:"+n.getY()+"px;" +
"width:"+n.getLen()+"px;'></div>\r\n");
}
}
//划竖线
for(Line n:all.getHLines()){
if(n.getLen()>0){
sb.append("<div style='position:absolute;border-left:1px solid gray;" +
"left:"+n.getX()+"px;" +
"top:"+n.getY()+"px;" +
"height:"+n.getLen()+"px;'></div>\r\n");
}
}
//画节点
for(Node n:all.getNodes()){
String[] row=(String[]) n.getData();
sb.append("<div style='position:absolute;border:1px solid gray;" +
"width:"+Graph.WIDTH_NODE+"px;height:"+Graph.HEIGHT_NODE+"px;" +
"left:"+n.getX()+"px;" +
"top:"+n.getY()+"px;'>" +
row[1]+"<br/>("+row[0]+")"+
"</div>\r\n");
}
sb.append("</div>");
return sb.toString();
}
private DataProvider dataProvider;
public void setDataProvider(DataProvider dataProvider) {
this.dataProvider=dataProvider;
}
}
2、Graph (画图形)
package yfzx.ex01;

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

public class Graph {
public static int HEIGHT_NODE=40;  //节点参数
public static int WIDTH_NODE=120;
public static int PADDING_HORIZONTAL=20;
public static int PADDING_VERTICAL=20;
private Object topNodedata;
private DataProvider dataProvider;
private List<Node> nodes=new ArrayList<Node>(); //节点
private List<Line> vLines=new ArrayList<Line>(); //横线
private List<Line> hLines=new ArrayList<Line>(); //竖线
private List<int[]> scopes=new ArrayList<int[]>();//辅助信息,每行最做和最右的节点位置,如果这行没有节点则为null
public void setDataProvider(DataProvider dataProvider) {
this.dataProvider=dataProvider;
}
public void setData(Object data) {
this.topNodedata=data;
}
/**
* 构建图形
*/
public void buildGraph() {
List<Object> subs=dataProvider.getSubNodeData(topNodedata);
if(subs==null||subs.size()==0){
//仅有一个节点。
nodes.add(new Node(0,0,topNodedata));
scopes.add(new int[]{0,0});
}else{
//深度优先后续遍历节点。
int minX=Integer.MAX_VALUE;
int maxX=Integer.MIN_VALUE;
for(Object sub:subs){
Graph subG=new Graph();
subG.setDataProvider(dataProvider);
subG.setData(sub);
subG.buildGraph();
subG.moveToSub();
int topNodeX=combine(subG);
if(minX>topNodeX){minX=topNodeX;}
if(maxX<topNodeX){maxX=topNodeX;}
//补充所有竖线
Line horLine=new Line(topNodeX+WIDTH_NODE/2,HEIGHT_NODE+PADDING_VERTICAL/2,PADDING_VERTICAL/2);
hLines.add(horLine);

}
//补充横线和中间的竖线。
Line horLine=new Line((minX+maxX+WIDTH_NODE)/2,HEIGHT_NODE,PADDING_VERTICAL/2);
hLines.add(horLine);
Line verLine=new Line(minX+WIDTH_NODE/2,HEIGHT_NODE+PADDING_VERTICAL/2,maxX-minX);
vLines.add(verLine);