你好,我是小黄,一名独角兽企业的Java开发工程师。
感谢茫茫人海中我们能够相遇,
俗话说:当你的才华和能力,不足以支撑你的梦想的时候,请静下心来学习,
希望优秀的你可以和我一起学习,一起努力,实现属于自己的梦想。
上一章我们讲解了关于图的搜索方法,主要是深度优先搜索和广度优先搜索,两种方法的搜索方式各有优点
不知道大家在日常工作中有没有碰到这种情况:
比如,我们只有完成工作一之后,才能去完成工作二、工作三,当工作二和工作三同时完成时,我们的工作四才开始开始
简单来说,当前工作必须依赖别的工作完成之后,才能实施工作,那么我们怎么判断哪一份工作需要提前完成呢?
这就是我们今天要讲的 拓扑排序
在图论中,拓扑排序(Topological Sorting)是一个有向无环图的所有顶点的线性序列。
且该序列必须满足下面两个条件:
对于上图来说,拓扑排序可以帮我们做点什么呢?
在常见的风控公司,有这样一个功能:决策流
简单来说,用户通过配置规则、dubbo服务,做一个流式的计算,如图所示:
这是一个比较简单的决策流,它由三个策略集编排,并有起始和结束,是符合BPMN规范的
我们的决策流在执行时,通过拓扑排序去判断每一个策略集完成的前后顺序,进行决策的判断
而dubbo接口的作用,通过远程服务调用,获取我们需要的信息去进行决策的判断,最终获取一个分数
组装成图的思路可见:给我5分钟,带你秒杀所有图算法之图的对象化描述
拓扑排序的思路:对于当前图中入度为0的点,即为当前可以执行操作的点
简单理解就是:当前的点,没有人指向他
对于上述思路,我们简单的遍历一遍所有点,可以得出第一次需要执行的点
当我们把第一个点给使用掉之后,我们需要将该点所连接的点的入度减一
public static void getScore(DecisionFlowGraph graph, HashMap<String, String> map) {
// 使用一个队列
Queue<DecisionFlowPoint> queue = new LinkedList<>();
// 遍历所有的点,找到入度为 0 的点
for (DecisionFlowPoint point : graph.points.values()) {
// 入度为0
if (point.in == 0) {
queue.add(point);
}
}
// 当前的队列不为空
while (!queue.isEmpty()) {
// 弹出当前队列的头
DecisionFlowPoint point = queue.poll();
// 使用当前该点代表的策略集
finalScore = finalScore + resolve(point, map);
// 将该点所连接的点的入度减一
for (DecisionFlowPoint next : point.points) {
next.in--;
if (next.in == 0) {
queue.add(next);
}
}
}
}
整个流程的代码由于太长的原因,在这里就不展示了,有兴趣的可以公众号回复:算法源码
简单来说,拓扑排序在我们实际业务中,用到的场景也是挺多的
比如:文中提到的决策流、工作流等
当然,看完本篇文章之后,也需要大量的场景去进行练习,不然容易生疏
本期的内容就到这里,下期将会讲述 最小生成树(Prim、Kruskal) 算法。
我是一名独角兽企业的Java开发工程师,希望可以点个关注呀,有问题可以留言或者私信加我微信,我们下期再见!