matlab 无向拓扑图,无向图绘画树状拓扑图算法

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

该需求难点如下:

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

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

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

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

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

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

效果图如下:

0bc6b890a961?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

直接看图:

0bc6b890a961?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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

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

0bc6b890a961?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

下面贴上部分代码:

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;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357602.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java Mail+MYSQL+Tomcate+jsp实现企业快信系统

导读:首先对企业快信的开发进行了较深入的研究,然后对短信发送与邮件发送原理进行了介绍,接下来对系统的概要设计、功能模块、数据库设计,以及名片夹管理功能与邮件发送功能的具体实现作了细致阐述,最后是系统效果的展示。企业快信系统是一个集短信与邮件为一体的移动商务…

SQL存储过程分页(通用的拼接SQL语句思路实现)

多表通用的SQL存储过程分页 案例一&#xff1a; USE [Community] GO/****** Object: StoredProcedure [dbo].[Common_PageList] Script Date: 2016/3/8 13:44:58 ******/ SET ANSI_NULLS ON GOSET QUOTED_IDENTIFIER ON GOCREATE PROCEDURE [dbo].[Common_PageList] ( tab …

odbc连接oracle失败,大神解答win7系统ODBC无法连接ORACLE的处理方案

随着电脑的使用率越来越高&#xff0c;我们有时候可能会遇到win7系统ODBC无法连接ORACLE问题&#xff0c;如果我们遇到了win7系统ODBC无法连接ORACLE的问题&#xff0c;要怎么处理win7系统ODBC无法连接ORACLE呢&#xff1f;我们只用1)操作系统是Win7 x64&#xff0c;客户端是Or…

spring-mvc教程_使用MVC模式制作游戏-教程和简介

spring-mvc教程游戏开发中一种有用的体系结构模式是MVC&#xff08;模型视图控制器&#xff09;模式。 它有助于分离输入逻辑&#xff0c;游戏逻辑和UI&#xff08;渲染&#xff09;。 在任何游戏开发项目的早期阶段&#xff0c;它的用途很快就会被注意到&#xff0c;因为它可以…

web前端开发需要学什么(包含前端学习路线)

前端开发&#xff0c;做到后面&#xff0c;是可以走很多方向的&#xff1b;但是要保证后期的平滑过度&#xff0c;前期还是要把一些必须的知识搞扎实的&#xff1b;web前端开发需要学什么环境搭建前端环境很好搭建&#xff0c;编辑器浏览器即可。浏览器推荐使用 Chrome行业内主…

2015年必火的五个Html5移动开发工具推荐

NO.1 DCloudHBuilder:基于HTML5开发工具 中文官网&#xff1a;http://www.dcloud.io/ DCloudHBuilder:基于HTML5开发工具是当前最快的HTML开发工具&#xff0c;强大的代码助手帮你快速完成开发&#xff0c;最全的语法库和浏览器兼容 性数据让浏览器碎片化不再头痛&#xff0c…

oracle 库存管理系统,库存管理系统

内容介绍原文档由会员 刘阳 发布库存管理系统页数 14 字数 9186[摘要]库存管理系统是生产、计划和控制的基础。本系统通过对仓库、货位等帐务管理及入&#xff0f;出库类型、入&#xff0f;出库单据的管理&#xff0c;及时反映各种物资的仓储、流向情况&#xff0c;为生产管理和…

想当程序员,如何判断自己是否适合当前端程序员?

说在前面&#xff1a;有粉丝提问说自己并不确定学前端&#xff0c;因为自己还没有工作&#xff0c;想做程序员&#xff0c;想问问做哪个方向比较有前途&#xff1b; 有两三个小伙伴这么问的&#xff0c;感觉很有意义&#xff0c;拿出来单独说说比较好。 目录 程序员有哪些选择&…

从WildFly 9(子系统)中运行OkHttpClient

几天前&#xff0c; WildFly 9发布了&#xff0c;可以肯定的重点之一是Undertow Web子系统中对HTTP / 2.0的支持。 由于Hawkular最近已开始使用WildFly 9&#xff08;从8.2开始&#xff09;作为其基础服务器&#xff0c;因此尝试将http2用于从Hawkular-Wildfly-Monitor客户端到…

oracle19c方言,JFinal框架操作oracle数据库

JFinal框架操作oracle数据库&#xff0c;需要在configPlugin()方法中配置链接oracle数据库的相关配置配置JFinal数据库操作插件&#xff0c;configPlugin方法这里我加载jdbc.properties配置文件实在configConstant加载的Overridepublic void configConstant(Constants me) {loa…

个税社保

资料来源&#xff1a;http://finance.qq.com/cross/20160218/H9cM96A8.html?pgv_refaio2015&ptlang2052转载于:https://www.cnblogs.com/weikang/p/5200832.html

前端程序员如何选择适合自己的培训机构

web前端开发培训哪家好这个主要是根据自己的情况来选择&#xff0c;本篇文章主要分享怎么选择适合自己的培训机构市场上有哪些培训机构以及所在位置既然关心哪家培训机构好&#xff0c;基本都是有报班学习的意向&#xff0c;所以就不多说自学和报班的区别了&#xff1b;我是不排…

linux c文件属性,【linux c learn 之stat】获取文件的属性

NAMEstat 获取文件属性这个函数位于头文件里函数原型&#xff1a;int stat(const char *path, struct stat *buf);參数&#xff1a;path 文件路径文件名称buf 指向buffer的指针返回值&#xff1a;-1 遇到错误0 成功返回函数作用&#xff1a;把path文件的信息拷贝到指…

!function(){}()

http://my.oschina.net/u/2331760/blog/468672?p{{currentPage1}} ( function(){…} )()和( function (){…} () )是两种javascript立即执行函数的常见写法&#xff0c;最初我以为是一个括号包裹匿名函数&#xff0c;再在后面加个括号调用函数&#xff0c;最后达到函数定义后立…

altium designer 10哪个作者写的好 。

问题截图&#xff1a; 博主解答&#xff1a; 其实这种书籍基本内容都差不多&#xff0c;很多都是作者来回借鉴&#xff0c;我们能根据自己的需要学到知识即可。

orm查询部分字段_ORM问题第2部分–查询

orm查询部分字段在我以前关于对象关系映射工具&#xff08;ORM&#xff09;的帖子中&#xff0c;我讨论了在处理当今常见的ORM&#xff08;包括Hibernate&#xff09;时遇到的各种问题。 其中包括与从POJO生成架构有关的问题&#xff0c;实际性能和不断出现的维护问题。 本质上…

新浪微博开发-添加子视图控制器设置颜色

一.添加子视图控制器 二.设置颜色 设置颜色&#xff1a;两种方法 一种较为繁琐&#xff0c;详见视频 第二种&#xff1a; //设置颜色 self.tabBar.tintColor UIColor.orangeColor()转载于:https://www.cnblogs.com/torrescx/p/5237142.html

linux ssh无需密码,linux下 ssh 实现无需密码的远程登陆

主机A(OpenSUSE12.1):119.78.222.95主机B (Fedora16): 202.122.25.361.主机A:生成秘钥对id_rsa和id_rsa.publinux-9juc:~ # ssh-keygen -t rsaGenerating public/private rsa key pair.Enter file in which to save the key (/root/.ssh/id_rsa):Created directory /root/.ssh.…

Android studio的sdk tools下没有LLDB的解决办法

粉丝提问&#xff1a; 博主解答: 解决办法&#xff1a; 点击setting--》plugins--》找到“Android Support”选项&#xff0c;并勾选&#xff0c;然后会提示重启android studio &#xff0c;点击重启&#xff0c;ok&#xff0c;如果已经设置好SDK的路径的话&#xff0c;问题解…

随机JCache内容:多个提供程序和JMX Bean

JCache&#xff08;JSR 107&#xff09;是用于缓存的Java标准…足够了。 没有更多介绍性的东西。 这是一则速成文章&#xff0c;内容涉及 多个JCache提供程序配置&#xff0c;以及 功能&#xff1a;通过JMX Mbeans的JCache统计信息 管理多个JCache提供程序 如果您只使用一个…