试想下这个么个场景:用户可以自己配置多个公式,公式与公式之间又有依赖关系。比如A=B+C ,B=C+D。需要做个算法来排序这些公式。实际我们可以分为两个步骤来看这个问题。
1,配置的公式之间不能死循环依赖。比如A=B+C ,B=A+C。这种A依赖于B,那就的先算B。但是B又依赖于A,的先算A。这就成了死循环,这种必须检测出来,提示用户配置错误。
2,依赖的公式之间必须要排序,这样才能保证计算结果正确。比如:A=B+C ,B=C+D。那么公式排序下来B=C+D就要先算,A=B+C就的后算。
我们定义公式为:
class Formula{//公式左边属性private key;//公式右边属性列表private Set<String> attributes;//公式深度private int depth;
}
我们先看死锁检测:
public void check(List<Formula> formulas){LinkedList<Formula> formulaLists = new LinkedList<>(formulas);Formula formula;while(Objects.nonNull(formula = formulaLists.poll())){TreeSet<String> feeSets = new TreeSet<>();relyOn(formula,feeSets,formulas);}}public void relyOn(Formula formula,Set<String> formulaKeyList,List<Formula> formulas){//将自己加进去formulaKeyList.add(formula.getKey());//遍历属性for(String attr:formula.getAttributeList()){if(formulaKeyList.contains(attr)){//在公式列表属性里又找到了自己}//继续找到依赖的公式列表(从formulas里找)List<Formula> feeRelationList = null;//遍历feeRelationList将formual、sets、formulas再次调用dependsOn//注意sets需要新定义并将formulaKeyList放进去}}
死锁完了再看依赖排序:
public List<Formula> pinfoSort(List<Formula> formulas) {LinkedList<Formula> formulaLinkedList = new LinkedList<>(formulas);//定义公式列表AFormula formula;while (Objects.nonNull(formula = formulaLinkedList.poll())) {int depth = getDepth(formula.getAttributes(), formulas);formula.setDepth(depth);//往公式列表A加入公式formula}//再按深度排序return 公式列表A;}public int getDepth(Set<String> attributeList, List<Formula> formulas) {int depth = 0;if (Objects.isNull(attributeList) || attributeList.size() == 0) {return depth;}int max = 0;for (String attr : attributeList) {List<Formula> feeRelationList = 继续查找公式依赖列表for (Formula formula : feeRelationList) {depth = getDepth(formula.getAttributeList(), formulas);max = Math.max(depth, max);}}return max + 1;}