基于目前Network项目需要,研究相关树形算法

该需求难点如下:

1、目前拓扑图是无向图,而树大多数都是基于有向图来画的,无法确定根节点

2、网络拓扑中存在回环问题,导致链路可能会存在重叠问题

针对问题1,目前根据所有节点的连通度来计算得出连通度最大的点作为根节点。

问题2目前没有完美的解决方案。

目前这边demo的算法分为2种

1、根据每层叶子节点个数切割X轴坐标,然后平均分布在一条直线上。

效果图如下:

代码比较简单,暂时就不公布了。

2、类似于一种递归的方式,从第一层叶子节点开始切割X轴,第二层叶子节点的范围不能超过上层节点之间的节点间距。

直接看图:

这种方式的弊端显而易见,如果后面存在大量叶子节点的枝节点,那么这里的叶子会非常密集

改变一下根节点样子或许会好一些,但是这边会出现回路重合链路问题:

下面贴上部分代码:

public ResponseEntity getTreeTopo() {

NodeList nodeList = new NodeList();

HashMap nodeCountMap = new HashMap<>();

//统计所有节点的连通度

for (int i = 0; i < lineTempList.size(); i++) {

if (nodeCountMap.containsKey(lineTempList.get(i).getUplinkNodeId().toString())) {

nodeCountMap.get(lineTempList.get(i).getUplinkNodeId().toString())

.setCount(nodeCountMap.get(lineTempList.get(i).getUplinkNodeId().toString()).getCount() + 1);

} else {

Connectivity connectivity = new Connectivity();

connectivity.setCount(1);

nodeCountMap.put(lineTempList.get(i).getUplinkNodeId().toString(), connectivity);

}

if (nodeCountMap.containsKey(lineTempList.get(i).getNodeId().toString())) {

nodeCountMap.get(lineTempList.get(i).getNodeId().toString())

.setCount(nodeCountMap.get(lineTempList.get(i).getNodeId().toString()).getCount() + 1);

} else {

Connectivity connectivity = new Connectivity();

connectivity.setCount(1);

nodeCountMap.put(lineTempList.get(i).getNodeId().toString(), connectivity);

}

}

//找到最大连通度的节点

int maxConnectivity = 0;

String rootNodeId = "";

for(String nodeId : nodeCountMap.keySet()) {

if(nodeCountMap.get(nodeId).getCount()>maxConnectivity) {

maxConnectivity = nodeCountMap.get(nodeId).getCount();

rootNodeId = nodeId;

}

}

int treeLevel = 1; //树高度

Set nodeSet = new HashSet<>();//记录所有已经分配过坐标的节点,用于查重

Map nodePositionMap = new HashMap<>();//记录所有节点坐标

Map subNodesCountMap = new HashMap<>();

rootNodeId="35";//手工设置根节点

nodeSet.add(rootNodeId);

NodeListInner rootNode = new NodeListInner();

rootNode.setNodeId(rootNodeId);

rootNode.setX("2000");

rootNode.setY("400");//假设画布为4000*4000

nodeList.add(rootNode);

nodePositionMap.put(rootNodeId, rootNode);

//根节点放在(2000,400)位置

List subPoint = getSubPoint(rootNodeId, nodeSet, subNodesCountMap);

subNodesCountMap.get(rootNodeId).setSpace(3800);//两边各留100空间

List parentPoint = new ArrayList<>();//需要保留父节点的信息

Point rootPoint = new Point();

rootPoint.setNodeId(rootNodeId);

rootPoint.setParentId(null);

parentPoint.add(rootPoint);

while (subPoint.size() != 0) {// 如果遍历到树的最高一层,则结束循环

//根据父节点的位置来分配叶子节点的位置

for(int j=0;j

if(subNodesCountMap.get(parentPoint.get(j).getNodeId()).getCount()==0) {

continue;

}

int gap = subNodesCountMap.get(parentPoint.get(j).getNodeId()).getSpace() / subNodesCountMap.get(parentPoint.get(j).getNodeId()).getCount();//子节点得到点与点之间的间距距离

int rightDeviation = 0;//单数往右偏移

int leftDeviation = - gap;//双数往左偏移

//获得子节点数据

List point = new ArrayList<>();

point = getSubPoint(parentPoint.get(j).getNodeId(), nodeSet, subNodesCountMap);

//遍历节点然后赋予坐标值

for(int i=0;i

if(!subNodesCountMap.containsKey(point.get(i).getNodeId())) {

NodeCount nodeCount = new NodeCount();

nodeCount.setSpace(gap);

subNodesCountMap.put(point.get(i).getNodeId(), nodeCount);

} else {

subNodesCountMap.get(point.get(i).getNodeId()).setSpace(gap);//这一个迭代的子节点是下一个迭代的父节点

}

NodeListInner node = new NodeListInner();

node.setNodeId(point.get(i).getNodeId());

if((i+1)%2==1) {//单数往右偏移

node.setX((rightDeviation+Integer.parseInt(nodePositionMap.get(parentPoint.get(j).getNodeId()).getX()))+"");

node.setY(400+treeLevel*400+"");

rightDeviation += gap;

} else {//双数往左偏移

node.setX((leftDeviation+Integer.parseInt(nodePositionMap.get(parentPoint.get(j).getNodeId()).getX()))+"");

node.setY(400+treeLevel*400+"");

leftDeviation -= gap;

}

nodePositionMap.put(point.get(i).getNodeId(),node);

nodeList.add(node);

nodeSet.add(node.getNodeId());

}

}

parentPoint = new ArrayList<>(subPoint);

subPoint.clear();

for (int i = 0; i < parentPoint.size(); i++) {//统计还有没有下一层叶子节点

subPoint.addAll(getSubPoint(parentPoint.get(i).getNodeId(), nodeSet, subNodesCountMap));

}

treeLevel+=1;

}

for (int j = 0; j < nodeList.size(); j++) {//补上节点之间的线

List lines = new ArrayList<>();

for (int i = 0; i < lineTempList.size(); i++) {

if (nodeList.get(j).getNodeId().equals(lineTempList.get(i).getUplinkNodeId().toString())) {

Line line = new Line();

line.setDest(lineTempList.get(i).getNodeId().toString());

line.setDestX(nodePositionMap.get(lineTempList.get(i).getNodeId().toString()).getX());

line.setDestY(nodePositionMap.get(lineTempList.get(i).getNodeId().toString()).getY());

lines.add(line);

}

}

nodeList.get(j).setLine(lines);

}

HttpHeaders headers = new HttpHeaders();

headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

headers.add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");

headers.add("Access-Control-Allow-Origin", "*");

headers.add("Access-Control-Allow-Headers", "x-requested-with,content-type");

return new ResponseEntity(nodeList, headers, HttpStatus.OK);

}

private List getSubPoint(String nodeId, Set nodeSet, Map subNodesCountMap) {

int count = 0;

List result = new ArrayList<>();

for (int i = 0; i < lineTempList.size(); i++) {

if (lineTempList.get(i).getUplinkNodeId().toString().equals(nodeId)) {

if (!nodeSet.contains(lineTempList.get(i).getNodeId().toString())) {

// 存储对端节点

Point point = new Point();

point.setNodeId(lineTempList.get(i).getNodeId().toString());

point.setParentId(nodeId);

result.add(point);

count++;

}

}

if (lineTempList.get(i).getNodeId().toString().equals(nodeId)) {

if (!nodeSet.contains(lineTempList.get(i).getUplinkNodeId().toString())) {

// 存储对端节点

Point point = new Point();

point.setNodeId(lineTempList.get(i).getUplinkNodeId().toString());

point.setParentId(nodeId);

result.add(point);

count++;

}

}

}

if(!subNodesCountMap.containsKey(nodeId)) {

NodeCount nodeCount = new NodeCount();

nodeCount.setCount(count);

subNodesCountMap.put(nodeId, nodeCount);

} else {

subNodesCountMap.get(nodeId).setCount(count);

}

return result;

}

matlab 无向拓扑图,无向图绘画树状拓扑图算法相关推荐

  1. POJ2182 Lost Cows(树状数组、二分、倍增)

    Lost Cows 题目链接 Description N (2 <= N <= 8,000) cows have unique brands in the range 1-N. In a ...

  2. java 有向无环图 树_拓扑排序-有向无环图(DAG, Directed Acyclic Graph)

    条件: 1.每个顶点出现且只出现一次. 2.若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面. 有向无环图(DAG)才有拓扑排序,非DAG图没有拓扑排序一说. 一 ...

  3. MATLAB | 全网唯一,使用MATLAB绘制精致的环形树状图

    绘制效果 请叫我平平无奇的绘图天才,这期一次性带来俩工具函数,分别是两层和三层的环形树状图,可以用来展示数据分类和层级: 理顺层级关系属实理得头秃,代码编写不易点个赞叭!! 由于工具函数过长,将被放在 ...

  4. MATLAB | 绘图复刻(三) | 分层聚类分析图:树状图+热图

    好久不见啊,今天时绘图复刻第三期,这期画的比较难应该文章也不会太短... 前段时间发现公众号SCIPainter发布了一期名为<如何对基因和蛋白质的表达丰度进行相关性分析>,其中有一幅图很 ...

  5. MATLAB | 全网唯一,使用MATLAB绘制矩形树状图

    绘制效果 全网唯一这四个字我都快说腻了,请叫我绘图小天才,又双叒叕写了一个工具函数发到了MATHWORKS,矩形树状图主要用于直观展示各个元素的分类和占比. 编写不易点个赞叭~~ 基本使用 需要准备一 ...

  6. Matlab绘制聚类分析树状图

    工作环境(蓝色粗体字为特别注意内容) 1.软件环境:Windows 7 Ultimate sp1.MatlabR2012b 32bit. 在使用Matlab做聚类分析的时候一般这样用: Y = pdi ...

  7. MatLab中画树状图方法treeplot(nodes)中描述树结构的矢量nodes的构造

    按要求需要用matlab画树状图,在网络上找到两句代码: nodes = [0 1 2 2 4 4 4 1 8 8 10 10]; treeplot(nodes); 画出了如下图: 其中矢量nodes ...

  8. 树状dp(这个人写得好多转来慢慢看)

    树状动态规划定义 之所以这样命名树规,是因为树形DP的这一特殊性:没有环,dfs是不会重复,而且具有明显而又严格的层数关系.利用这一特性,我们可以很清晰地根据题目写出一个在树(型结构)上的记忆化搜索的 ...

  9. 2023牛客寒假算法基础集训营4_20230130「向上取整」「夹逼dp」「lowbit科学+树状数组性质」「搜索」「倍增跳表」「莫队」

    6/13 教育场是有被教育到.(预计会鸽几题. 已过非太水的题们 //B //https://ac.nowcoder.com/acm/contest/46812/B//小构造小数学#include & ...

最新文章

  1. 列举一些RNN类模型的常见使用形式以及常见的应用
  2. 如何使用MatPlotLib绘制出具有两个 Y 轴的曲线图?
  3. oracle如何升序,oracle排序操作
  4. python list超出范围_使用lxmldjango/python-list索引超出范围
  5. 用vim看代码的常用指令
  6. 三个世界及其有关概念
  7. [react] render函数中return如果没有使用()会有什么问题?
  8. h5评论直接显示代码_全套H5教程免费学,让你0基础自学制作H5页面
  9. 下拉菜单,防鼠标反复触发
  10. latex安装包_Latex安装包及模版教程!数学专业必备!美赛神器!
  11. Python把汉字转换成拼音
  12. python查看微信撤回消息_python如何查看微信消息撤回
  13. 【转】VC动态内存分配PPT
  14. Linux——常用命令
  15. ZooKeeper Watcher注意事项
  16. java中的Map每次只能put一次,写段增强的put,可以一次put很多次
  17. Vue-CoreVideoPlayer 一款基于 vue.js 的轻量级、优秀的视频播放器组件
  18. Win10如何安装自带的XPS Viewer查看器
  19. Silverlight 2学习教程(四)
  20. ESP32-WROOM-32 ESP32 wifi模块基本参数与引脚定义

热门文章

  1. html如何与php,html页面怎么跟php文件连接
  2. 什么是卫星的有效载荷?
  3. html5画布funcition,2020前端基础知识学习第一节(示例代码)
  4. Windows编程初步(三)【说明:有敏感字眼已全删,不知道为啥还审核不通过】
  5. linux设置新硬盘权限,Linux 下挂载新硬盘以及更改为普通权限
  6. redis集群scan_Redis scan命令的一次坑
  7. 190. 颠倒二进制位
  8. Node.js 官方文档中文版
  9. 时间复杂度和空间复杂度[数据结构]
  10. Ajax.BeginForm无法调用 ajaxOptions的js函数