当前位置: 首页 > news >正文

品牌网站开发特点百度客服投诉中心

品牌网站开发特点,百度客服投诉中心,凡科网免费做网站,建设工程施工合同纠纷司法解释一本文记录如何通过拓扑排序,实现循环依赖判断 前言 一般提到循环依赖,首先想到的就是Spring框架提供的Bean的循环依赖检测,相关文档可参考: https://blog.csdn.net/cristianoxm/article/details/113246104 本文方案脱离Spring Be…

本文记录如何通过拓扑排序,实现循环依赖判断

前言

一般提到循环依赖,首先想到的就是Spring框架提供的Bean的循环依赖检测,相关文档可参考:

https://blog.csdn.net/cristianoxm/article/details/113246104

本文方案脱离Spring Bean的管理,通过算法实现的方式,完成对象循环依赖的判断,涉及的知识点包括:邻接矩阵图、拓扑排序、循环依赖。本文会着重讲解技术实现,具体算法原理不再复述

概念释义

1. 什么是邻接矩阵?

这里要总结的邻接矩阵是关于图的邻接矩阵;图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组来表示图;一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息;

图分为有向图和无向图,其对应的邻接矩阵也不相同,无向图的邻接矩阵是一个对称矩阵,就是一个对称的二位数组,a[i][j] = a[j][i];
邻接矩阵可以清楚的知道图的任意两个顶点是否有边;方便计算任意顶点的度(包括有向图的出度和入度);可以直观的看出任意顶点的邻接点;

本案例中,有向邻接矩阵图为进行拓扑排序的必要条件之一,其次为有向邻接矩阵图每个顶点的入度

2. 邻接矩阵的存储结构?

vexs[MAXVEX]这是顶点表;

arc[MAXVEX][MAXVEX]这是邻接矩阵图,也是存储每条边信息的二维数组。数组的索引是边的两个顶点,数组的数据是边的权值;

numVertexes, numEdges分别为图的顶点数和边数。

3. 有向邻接矩阵图顶点的入度?

在有向图中,箭头是具有方向的,从一个顶点指向另一个顶点,这样一来,每个顶点被指向的箭头个数,就是它的入度。从这个顶点指出去的箭头个数,就是它的出度

邻接矩阵的行号即代表箭头的出发结点,列号是箭头的指向结点,所以矩阵中同一行为1的表示有从第i个结点指向第j个结点这样一条边,而在同列为1就代表第j个结点被第i个结点指向,因此要求顶点的入度或出度,只需要判断同列为1的个数或同行为1的个数

4. 什么是拓扑排序?

拓扑排序的要素:
1.有向无环图;
2.序列里的每一个点只能出现一次;
3.任何一对 u 和 v ,u 总在 v 之前(这里的两个字母分别表示的是一条线段的两个端点,u 表示起点,v 表示终点);

根据拓扑排序的要素,可通过其有向无环来判断对象依赖是否存在循环。若对象组成的图可完成拓扑排序,则该对象图不存在环,即对象间不存在循环依赖。

拓扑排序除了通过有向邻接矩阵图实现外,还可以通过深度优先搜索(DFS)来实现。本案例中仅讲解前者。

5. 什么是循环依赖?

简单解释如下,若存在两个对象,若A创建需要B,B创建需要A,这两个对象间互相依赖,就构成了最简单的循环依赖关系。

编程示例

1. 对象实体

@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class RelationVo implements Serializable {/*** 唯一标识*/private String uniqueKey;/*** 关联唯一标识集合*/private List combinedUniqueKeys;}

2. 对象集合转换为有向邻接矩阵图

    /*** 将List集合转换为邻接矩阵图的二维数组形式** @param sourceList* @return*/public static int[][] listToAdjacencyMatrixDiagram(List sourceList) {List distinctRelationVoList = new ArrayList(sourceList);List keyCollect = distinctRelationVoList.stream().map(RelationVo::getUniqueKey).collect(Collectors.toList());for (RelationVo vo : sourceList) {vo.getCombinedUniqueKeys().forEach(child -> {if (!keyCollect.contains(child)) {// 若叶子节点不在集合中,补充List集合中单独叶子节点,目的是完成提供邻接矩阵图计算的入参keyCollect.add(child);RelationVo build = RelationVo.builder().uniqueKey(child).build();distinctRelationVoList.add(build);}});}// 顶点数:对象中出现的全部元素总数int vertexNum = keyCollect.size();/** 初始化邻接矩阵图的边的二维数组,1表示有边 0表示无边 权重均为1* 其中数组下标为边的两个顶点,数组值为对象边的权值(权值=是否有边*权重)*/int[][] edges = new int[vertexNum][vertexNum];// 计算邻接矩阵图for (int i = 0; i < vertexNum; i++) {RelationVo colVo = distinctRelationVoList.get(i);List colUniqueKeys = colVo.getCombinedUniqueKeys();for (int j = 0; j < vertexNum; j++) {RelationVo rowVo = distinctRelationVoList.get(j);String rowVertex = rowVo.getUniqueKey();if (CollUtil.isNotEmpty(colUniqueKeys)) {if (colUniqueKeys.contains(rowVertex)) {edges[i][j] = 1;} else {edges[i][j] = 0;}}}}return edges;}

3. 计算邻接矩阵图顶点的入度

     /*** 返回给出图每个顶点的入度值** @param adjMatrix 给出图的邻接矩阵值* @return*/public static int[] getSource(int[][] adjMatrix) {int len = adjMatrix[0].length;int[] source = new int[len];for (int i = 0; i < len; i++) {// 若邻接矩阵中第i列含有m个1,则在该列的节点就包含m个入度,即source[i] = mint count = 0;for (int j = 0; j < len; j++) {if (adjMatrix[j][i] == 1) {count++;}}source[i] = count;}return source;}

4. 对邻接矩阵图进行拓扑排序

    /*** 拓扑排序,返回给出图的拓扑排序序列* 拓扑排序基本思想:* 方法1:基于减治法:寻找图中入度为0的顶点作为即将遍历的顶点,遍历完后,将此顶点从图中删除* 若结果集长度等于图的顶点数,说明无环;若小于图的顶点数,说明存在环** @param adjMatrix 给出图的邻接矩阵值* @param source    给出图的每个顶点的入度值* @return*/public static List topologySort(int[][] adjMatrix, int[] source) {// 给出图的顶点个数int len = source.length;// 定义最终返回路径字符数组List result = new ArrayList(len);// 获取入度为0的顶点下标int vertexFound = findInDegreeZero(source);while (vertexFound != -1) {result.add(vertexFound);// 代表第i个顶点已被遍历source[vertexFound] = -1;for (int j = 0; j < adjMatrix[0].length; j++) {if (adjMatrix[vertexFound][j] == 1) {// 第j个顶点的入度减1source[j] -= 1;}}vertexFound = findInDegreeZero(source);}//输出拓扑排序的结果return result;}/*** 找到入度为0的点,如果存在入度为0的点,则返回这个点;如果不存在,则返回-1** @param source 给出图的每个顶点的入度值* @return*/public static int findInDegreeZero(int[] source) {for (int i = 0; i < source.length; i++) {if (source[i] == 0) {return i;}}return -1;}

5. 检查集合是否存在循环依赖

    /*** 检查集合是否存在循环依赖** @param itemList*/public static void checkCircularDependency(List itemList) throws Exception {if (CollUtil.isEmpty(itemList)) {return;}// 计算邻接矩阵图的二维数组int[][] edges = listToAdjacencyMatrixDiagram(itemList);// 计算邻接矩阵图每个顶点的入度值int[] source = getSource(edges);// 拓扑排序得到拓扑序列List topologySort = topologySort(edges, source);if (source.length == topologySort.size()) {// 无循环依赖return;} else {// 序列集合与顶点集合大小不一致,存在循环依赖throw new Exception("当前险种关系信息存在循环依赖,请检查");}}

单测用例

1. 测试物料-无循环依赖

示例JSON Array结构(可完成拓扑排序):
[{"uniqueKey":"A","combinedUniqueKeys":["C","D","E"]
},
{"uniqueKey":"B","combinedUniqueKeys":["D","E"]
},
{"uniqueKey":"D","combinedUniqueKeys":["C"]
}
]

2. 测试物料-存在循环依赖

示例JSON Array结构(不可完成拓扑排序):
[{"uniqueKey":"A","combinedUniqueKeys":["C","D","E"]
},
{"uniqueKey":"B","combinedUniqueKeys":["D","E"]
},
{"uniqueKey":"D","combinedUniqueKeys":["C"]
},
{"uniqueKey":"C","combinedUniqueKeys":["B"]
}
]

3. 单测示例

@Slf4j
public class CircularDependencyTest {/*** 针对集合信息判断该集合是否存在循环依赖*/@Testvoid testCircularDependencyList() throws Exception {String paramInfo = "[{\"uniqueKey\":\"A\",\"combinedUniqueKeys\":[\"C\",\"D\",\"E\"]},{\"uniqueKey\":\"B\",\"combinedUniqueKeys\":[\"D\",\"E\"]},{\"uniqueKey\":\"D\",\"combinedUniqueKeys\":[\"C\"]}]";// 序列化List list = JSONArray.parseArray(paramInfo, RelationVo.class);TopologicalSortingUtil.checkCircularDependency(list);}
}

作者:京东保险 侯亚东

来源:京东云开发者社区 转载请注明来源

http://www.dt0577.cn/news/8976.html

相关文章:

  • 没有独立ip如何解析网站seo综合查询平台
  • 做营销型网站价格网站外部优化的4大重点
  • 天津外贸公司网站制作营销 推广
  • 网站网页设计制作教程杭州seook优屏网络
  • 个人网站建设好之后怎么赚钱网络营销的期末试题及答案
  • .net网站开发工具介绍搜什么关键词你都懂的
  • 网站怎么做二维码相城seo网站优化软件
  • 做模特网站网络链接推广
  • 创意福州网站建设友情链接属于免费推广吗
  • 重庆哪家做网站超级外链推广
  • 公司网站去哪里做长春网站优化服务
  • 滨海做网站找哪家好关键词指数
  • 做笑话网站赚钱优化营商环境工作总结
  • 基层党组织标准化建设网站营销策划方案1000例
  • 做虾皮网站英文站友情链接去哪里查
  • 品牌推广网站怎么做湖北权威的百度推广
  • 南昌外贸网站建设网址创建
  • 合肥网站建设哪家公司好seo搜索引擎优化实训总结
  • 浙江微信网站建设直通车优化推广
  • 汽车网站怎么做最新网域查询入口
  • 上海市中小企业服务云seo网站优化详解
  • 之梦系统怎么修改网站标头图片百度贴吧官网
  • 真人做爰网站视频百度指数官网入口登录
  • 做网站要多少钱新乡花钱推广的网络平台
  • 阜阳北京网站建设北京seo的排名优化
  • 商业信息网站大全制作电商网站
  • 校园内部网站平台建设方案上海seo优化服务公司
  • 网站推广联盟百度爱采购优化排名软件
  • 知名企业破产seo怎么收费seo
  • 网站建设推荐郑国华刷钻业务推广网站