最近在一个项目中接触到一个算法,类似于构建生成树算法,但是还是有点不同,首先讲一下该算法的构建所需要实现的功能,如下图所示:
比如:要得到A的值,若是B和C的值不为空,那么A=B+C,若是B的值为空,那么就继续找父节点为B的节点信息,若D和E的值不为空,那么A=C+D+E,若是D为空,那么A的值是得到不到的,返回为空,若是D值不为空,E值为空,那么找E的孩子节点信息,若是G不为空的话,那么A=D+G-+C 本算法的大致意思就是这样,那么该如何实现呢?
再项目开发过程中,我是先考虑实现功能,在功能实现的基础上再考虑算法功能优化为题,该算法采用的是算法思想中的回溯法,首先看下该算法设计的步骤
1.构建树之前先建立一个实体类TreeModel,其中该类中包含三个参数,如下代码所示:
public class TreeModel {
private Long no;
private String scheduleid;
private Long fatherno;
public Long getNo() {
return no;
}
public void setNo(Long no) {
this.no = no;
}
public String getScheduleid() {
return scheduleid;
}
public void setScheduleid(String scheduleid) {
this.scheduleid = scheduleid;
}
public Long getFatherno() {
return fatherno;
}
public void setFatherno(Long fatherno) {
this.fatherno = fatherno;
}
public TreeModel(Long no, String scheduleid, Long fatherno) {
super();
this.no = no;
this.scheduleid = scheduleid;
this.fatherno = fatherno;
}
public TreeModel() {
super();
}
}
2.第一个参数是一个节点的标识,第二个是该节点的值,第三个参数对应的是父节点的标识,对于第一个节点A,父节点我标识为0,构建生成树的具体代码如下所示:
public class TreeModelUtil {
/**
* 构建树的形状,A中的id类似一个电路路由的id,父节点id值为11的代表的是第一层,
*下面的则是逐层遍历
* */
public String s="";
public String forRecursion(List<TreeModel> list,long pid){
for (int i = 0; i < list.size(); i++) {
// System.out.println("treemodelutil--->"+list.get(i).getNo()+"___"+list.get(i).getScheduleid()+"__"+list.get(i).getFatherno());
long id=list.get(i).getNo();
String scheduleid=list.get(i).getScheduleid();
if (list.get(i).getFatherno()==pid) {
Long flag=isendNode(list,id);
if (flag==1) {
if (scheduleid!=null) {
s+=scheduleid+"+";
}else {
forRecursion(list, id);
}
}
if(flag==2){
if (scheduleid!=null) {
s+=scheduleid+"+";
}else {
s+="不可测+";
}
}
}
}
return s;
}
public Long isendNode(List<TreeModel> list,long id){
//此处判断是不是根节点,不是根节点为1,是跟节点2
Long flag=(long)1;
List<Long> listFno=new ArrayList();
for (int i = 0; i < list.size(); i++) {
listFno.add(list.get(i).getFatherno());
}
if (listFno.contains(id)) {
//不是根节点
flag=(long)1;
}else{
//是根节点
flag=(long)2;
}
return flag;
}
该类中包含两个方法,第一个方法是构建生成树,第二个方法是判断是不是叶子节点。
3.先写一个测试类,如下:
public class TreeModelMain {
public void getTestResult(){
List<TreeModel> list = new ArrayList();
/**
* 构建树的形状,A中的id类似一个电路的id,父节点id值为11的代表的是第一层, 下面的则是逐层遍历
* treeModel中封装的是电路id,路由段对应的规则id和(再项目中是这么应用的),攥取得到的父类id
*/
TreeModel treeModel1 = new TreeModel((long) 11, "A", (long) 0);
TreeModel treeModel2 = new TreeModel((long) 22, null, (long) 11);
TreeModel treeModel3 = new TreeModel((long) 33, "C", (long) 11);
TreeModel treeModel4 = new TreeModel((long) 44, "D", (long) 22);
TreeModel treeModel5 = new TreeModel((long) 55, "E", (long) 22);
TreeModel treeModel6 = new TreeModel((long) 66, "F", (long) 33);
TreeModel treeModel7 = new TreeModel((long) 77, "G", (long) 55);
// TreeModel treeModel8 = new TreeModel((long) 88, "H", (long) 33);
// TreeModel treeModel9 = new TreeModel((long) 99, "I", (long) 33);
list.add(treeModel1);
list.add(treeModel2);
list.add(treeModel3);
list.add(treeModel4);
list.add(treeModel5);
list.add(treeModel6);
list.add(treeModel7);
// list.add(treeModel8);
// list.add(treeModel9);
TreeModelUtil tm=new TreeModelUtil();
String ss="";
ss=tm.forRecursion(list, 11);
if ( ss.contains("不可测")) {
ss="不可测";
System.out.println("不可测");
}else {
System.out.println("A=" + ss.substring(0, ss.length()-1));
} }
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeModelMain tmmain=new TreeModelMain();
tmmain.getTestResult();
}
}
上例的输出结果是:A=D+E+C
这是在B不可测的情况下得到的值。
若是修改D为空,哪儿就会输出不可测,得不到值的情况
本算法主要采用的是一个递归思想,通俗的话来说出了叶子节点之外,别的孩子节点始终会变成父亲,然后就这样递归下去,最后得到值,本算法中可能还存在很多的缺陷,能忘能够得到高手的指正。