正文
对多个结果和参数互相嵌套的式子进行排序
目的:式子按顺序执行一次,得到所有的结果
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 对多个结果和参数互相嵌套的式子进行排序
* 目的:式子按顺序执行一次,得到所有的结果
* 模拟数据格式:
* ["f_2268", "cal(f_2307+f_2276)"]
* ["f_2274", "cal(f_2247-f_2268)"]
* ["f_2276", "sum(f_2262)"]
*/
public class SortTest {
public static void main(String[] args) {
// 开始时间
long start = System.currentTimeMillis();
/**
* 模拟提取所有式子结果,存入一个集合中的行为
* 此时,集合中的元素是乱序的
* 预想:最终将集合里的元素可以按照正确的顺序排列
*/
List<String> sortedList = new ArrayList<String>() {{
// add("f_2268");
// add("f_2274");
// add("f_2276");
// add("公式1");
// add("公式2");
// add("公式3");
// add("公式4");
add("z");
add("f");
add("zz");
add("b");
add("g");
add("a");
add("d");
add("e");
add("c");
}};
/**
* 模拟构建结果和参数的关联关系
*/
Map<String, List<String>> tempMap = new HashMap<String, List<String>>() {{
// put("f_2268", Arrays.asList("f_2307", "f_2276"));
// put("f_2274", Arrays.asList("f_2247", "f_2268"));
// put("f_2276", Arrays.asList("f_2262"));
// put("公式3", Arrays.asList("公式2"));
// put("公式1", Arrays.asList("公式3", "公式4"));
// put("公式4", Arrays.asList(""));
// put("公式2", Arrays.asList("公式4"));
put("z", Arrays.asList("a", "d", "e", "g"));
put("f", Arrays.asList("b"));
put("b", Arrays.asList("a"));
put("g", Arrays.asList("a", "d", "c"));
put("a", Arrays.asList(""));
put("d", Arrays.asList("b"));
put("e", Arrays.asList("a"));
put("c", Arrays.asList(""));
put("zz", Arrays.asList("z"));
}};
/**
* 将互相嵌套的式子存入一个集合中,方便后续处理
*/
Map<String, HashSet<String>> mapping = new HashMap<>();
for (int i = 0; i < sortedList.size(); i++) {
HashSet<String> set = new HashSet<>();
for (int j = 0; j < sortedList.size(); j++) {
if (j == i) continue;
if (tempMap.get(sortedList.get(i)).contains(sortedList.get(j))) {
set.add(sortedList.get(j));
}
}
mapping.put(sortedList.get(i), set);
}
// 取出没有被引用的式子
List<String> independentList = sortedList.stream().filter(s -> mapping.get(s).size() == 0).collect(Collectors.toList());
// 取出被引用的式子
List<String> referencedList = sortedList.stream().filter(s -> mapping.get(s).size() != 0).collect(Collectors.toList());
// List<String> newSortedList = new ArrayList<>();
// newSortedList.addAll(independentList);
// newSortedList.addAll(referencedList);
// 将两个集合合并,没有被引用的式子在前,被引用的式子在后
// 减少循环次数
List<String> newSortedList = Stream.of(independentList, referencedList).flatMap(Collection::stream).collect(Collectors.toList());
int count = 0;
// 递归排序
loop(mapping, newSortedList, count, newSortedList.size());
System.out.println("===============================================================================");
System.out.println("最终排序为:");
newSortedList.forEach(System.out::println);
System.out.println("耗时:" + (System.currentTimeMillis() - start) + "ms");
}
public static BigInteger getFactorial(int num) {
BigInteger result = BigInteger.ONE;
for (int i = 1; i <= num; i++)
result = result.multiply(BigInteger.valueOf(i));
return result;
}
/**
* 递归排序
*
* @param tempMap 结果和参数的关联关系
* @param newSortedList 最终排序的集合
* @param count 当前递归次数
* @param maxCount 最大递归次数,超过则说明存在循环引用的现象,终止递归!
*/
private static void loop(Map<String, HashSet<String>> tempMap, List<String> newSortedList, int count, int maxCount) {
count++;
if (count > maxCount) {
throw new RuntimeException("操作异常,原因:发现多个计算公式的参数和结果循环引用!");
}
System.out.println("===============================================================================");
System.out.println("开始了第" + count + "次递归");
// 记录是否需要调换位置的标志
boolean flag = false;
for (int i = 0; i < newSortedList.size() - 1; i++) {
int sort = i + 1;
System.out.println("///");
System.out.println("第" + sort + "次循环");
System.out.println("被比较参数:" + newSortedList.get(i));
for (int j = i + 1; j < newSortedList.size(); j++) {
System.out.println("比较参数:" + newSortedList.get(j));
if (tempMap.get(newSortedList.get(i)).contains(newSortedList.get(j))) {
System.out.println("{");
System.out.println("\t\t发现需要调换位置的参数:");
System.out.println("\t\t前参数:" + newSortedList.get(i));
System.out.println("\t\t后参数:" + newSortedList.get(j));
System.out.println("}");
Collections.swap(newSortedList, i, j);
flag = true;
}
}
}
// 如果存在需要调换位置的参数,则说明元素排列还不稳定,需要再进行一次递归排序
if (flag) {
loop(tempMap, newSortedList, count, maxCount);
}
}
}