package com.bs.weather.util.SuanFa.ZhuLiu_TarJan;
import com.bs.weather.util.SuanFa.Entity.SetNewMapReturn;
import java.util.*;
public class ZhuLiu {
private final float INF = Float.MAX_VALUE;
private float[][] distance; //距离矩阵
private int[] minArray; //每个节点入边最小的数组
private int[][] resultArray; //入边可达性矩阵
private boolean[] ifInStack; //判断是否在栈中
private boolean[] ifVisit; //判断是否访问过
private Stack<Integer> stack; //tarjan栈
private List<ArrayList> allRingList; //环总集合
private int firstPoint; //起点
private int ringCount = 0; //环数
private List<float[][]> allDistanceList;//存储每一层递归的distance方便做展开操作时使用
private List<SetNewMapReturn> allsetNewMapReturnList;//存储每一层递归的SetNewMapReturn方便做展开操作时使用
//tarjan的三个参数
int[] dfn; //时间戳
int[] low; //low一致的为同一环
int index; //索引值
public ZhuLiu(float[][] distance, int firstPoint) {
int l = distance.length;
this.firstPoint = firstPoint;
this.distance = distance;
dfn = new int[l];
low = new int[l];
ifInStack = new boolean[l];
ifVisit = new boolean[l];
stack = new Stack<>();
resultArray = new int[l][l];
allRingList = new ArrayList<>();
minArray = new int[l];
allDistanceList = new ArrayList<>();
allsetNewMapReturnList = new ArrayList<>();
init();
}
public void init() {
//初始化最短入边矩阵值都为-1
for (int i = 0; i < minArray.length; i++) {
minArray[i] = -1;
}
}
//朱刘算法
public int[] runZhuLiu() {
//最短距离临时变量
float minLengthTmp;
//选取每个节点的最小的入边(朱刘第一步)
for (int i = 0; i < distance.length; i++) {
minLengthTmp = Float.MAX_VALUE;
for (int j = 0; j < distance.length; j++) {
if (i != j) {
if ((minLengthTmp > distance[j][i])) {
minLengthTmp = distance[j][i];
//diePointList存储入边信息,例如diePointList.get(0)为1则0节点min入边为 1-0
minArray[i] = j;
} else if (minLengthTmp == distance[j][i] && minArray[i] != -1 && minArray[minArray[i]] == i) {
//假设A-B与C-B距离一致,此时A-B并且B-A,那么要用C-B替换A-B以免形成环
//diePointList存储入边信息,例如diePointList.get(0)为1则0节点min入边为 1-0
minArray[i] = j;
}
}
}
}
//将起点设置为没有最短入边,也就是起点不可达
minArray[firstPoint] = -1;
//根据minArray,形成新的可达关系矩阵
for (int i = 0; i < minArray.length; i++) {
if (minArray[i] != -1) {
//当前节点有入边
//将minArray中可达的距离矩阵坐标至为1
resultArray[minArray[i]][i] = 1;
}
//由于最外层接口做了可达性验证所以不会出现没有入度的节点除了-1
// else if (i != firstPoint) {
// //当前节点没有入边&&当前城市不是起点因为起点没有入边
// //需要完善
// System.out.println("产生了不可达节点遍历结果集可找出");
// }
}
//如果有环进行缩环为点,如果没有返回结果(缩环为点 朱刘第二步)
if (ifHaveRing(firstPoint)) {
//有环进行缩环为点,形成新图(会再次递归朱刘直到没有环)
SetNewMapReturn setNewMapReturn = shrinkagePoint(distance, firstPoint, allRingList, new SetNewMapReturn());
//判断新图是否有环
ZhuLiu zhuliu = new ZhuLiu(setNewMapReturn.getDistanceTmp(), setNewMapReturn.getFirstPointTmp());
int[] newMinArray = zhuliu.runZhuLiu();
// if (newMinArray!=null){} 空指针异常处理但是会少点
return unfoldMap(setNewMapReturn, newMinArray);
} else {
//无环构造图形
//输出---输出没有环直接构造的图形结果
// System.out.println("无环构造图形");
// for (int i = 0; i < minArray.length; i++) {
// if (minArray[i] != -1) {
// //起点不可以有入边
// System.out.println(minArray[i] + "---->" + i);
// }
// }
// System.out.println();
//拿到当前传入的distance,此时的distance就是上一层的更新权值后的距离矩阵,根据其及索引关系进行展开
return minArray;
}
}
//判断是否有环(参数为起点),tarjan
public boolean ifHaveRing(int firstPoint) {
boolean ifHaveRingMark = true;
//遍历入边可达矩阵,判断是否有环
for (int i = 0; i < resultArray.length; i++) {
//将没走过的节点传入,并且当前节点不等于出发点
if (!ifVisit[i]) {
//还有节点没走到继续遍历
recursionHaveRing(i, firstPoint);
}
}
if (ringCount == 0) {
//无环
ifHaveRingMark = false;
}
// //最短可达距离顺序输出
// System.out.println("--------------");
// for (Integer i : resultRingList) {
// System.out.println(i);
// }
// System.out.println("--------------");
return ifHaveRingMark;
}
//判断是否有环递归函数
public void recursionHaveRing(int u, int firstPoint) {
//u不等于起始点,因为起始点并没有入边,所以起始点不用加入tarjan,resultArray中起始点入边都为-1
if (u != firstPoint) {
//给dfn和low赋值
dfn[u] = low[u] = index++;
//当前节点入栈
stack.push(u);
//标记当前节点在栈中
ifInStack[u] = true;
ifVisit[u] = true;
//开始遍历其可达节点
for (int i = 0; i < resultArray.length; i++) {
//首先保证u-i可以走通
if (resultArray[u][i] == 1) {
//u-i可以走通
if (!ifInStack[i]) {
//i节点不存在栈中
recursionHaveRing(i, firstPoint);
//递归完成进行low的更新,如果low[u]<low[i]证明i节点的后续的节点与u节点前面的节点形成了环,所以他们的low都需要更新为该环中最小的low
low[u] = Math.min(low[u], low[i]);
} else {
//如果当前点在栈中
//更新low,u节点的low如果小于i节点的dfn那么形成环,更新low[u]
low[u] = Math.min(low[u], dfn[i]);
}
}
}
if (dfn[u] == low[u]) {
//是否成环标志
boolean ringMark = false;
//环集合
ArrayList<Integer> ringList = new ArrayList<>();
//每个节点只有一个入边所以不需要一个节点访问2次的情况(如果出现直接过滤即可)所以是否访问过的矩阵状态不需要更新
while (stack.size() != 0 && stack.peek() != u) {
//如果栈顶元素不等于u则成环
ringMark = true;
//将是否在栈状态改�
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
JAVA实现根据实时天气地图景点数据_智能推荐旅游景点路线系统源码+项目说明.7z 主要针对计算机相关专业的正在做毕设的学生和需要项目实战的Java学习者。 也可作为课程设计、期末大作业。包含:项目源码、数据库脚本、项目说明等,该项目可以直接作为毕设使用。 也可以用来学习参考借鉴!
资源推荐
资源详情
资源评论
收起资源包目录
JAVA实现根据实时天气地图景点数据-智能推荐旅游景点路线系统源码+项目说明.7z (304个子文件)
layui.css 68KB
layer.css 14KB
xadmin.css 10KB
layui.mobile.css 10KB
laydate.css 7KB
column.css 7KB
from1.css 2KB
login.css 2KB
style.css 2KB
basic.css 1KB
code.css 1KB
theme5.css 590B
font.css 546B
theme4.css 309B
theme1.css 304B
theme3.css 297B
theme2.css 288B
iconfont.eot 48KB
iconfont.eot 40KB
59.gif 10KB
22.gif 10KB
24.gif 8KB
13.gif 7KB
16.gif 7KB
39.gif 6KB
64.gif 6KB
63.gif 6KB
50.gif 6KB
loading-0.gif 6KB
4.gif 6KB
1.gif 5KB
42.gif 5KB
71.gif 5KB
21.gif 5KB
20.gif 5KB
29.gif 5KB
70.gif 4KB
5.gif 4KB
17.gif 4KB
27.gif 4KB
9.gif 4KB
44.gif 4KB
11.gif 4KB
8.gif 4KB
3.gif 4KB
23.gif 4KB
34.gif 4KB
41.gif 4KB
38.gif 4KB
65.gif 3KB
32.gif 3KB
45.gif 3KB
7.gif 3KB
12.gif 3KB
26.gif 3KB
60.gif 3KB
2.gif 3KB
40.gif 3KB
25.gif 3KB
19.gif 3KB
66.gif 3KB
18.gif 3KB
46.gif 3KB
10.gif 3KB
28.gif 3KB
51.gif 3KB
57.gif 3KB
67.gif 3KB
0.gif 3KB
48.gif 3KB
43.gif 3KB
30.gif 2KB
61.gif 2KB
33.gif 2KB
69.gif 2KB
14.gif 2KB
47.gif 2KB
36.gif 2KB
49.gif 2KB
58.gif 2KB
6.gif 2KB
54.gif 2KB
53.gif 2KB
56.gif 2KB
62.gif 2KB
31.gif 2KB
55.gif 2KB
35.gif 2KB
15.gif 2KB
loading-2.gif 2KB
37.gif 1KB
68.gif 1KB
52.gif 777B
loading-1.gif 701B
member-list.html 14KB
getinfo.html 13KB
index.html 11KB
echarts4.html 9KB
day15-listN.html 9KB
weathertrend.html 9KB
共 304 条
- 1
- 2
- 3
- 4
资源评论
- fengkai9912023-04-06发现一个宝藏资源,赶紧冲冲冲!支持大佬~
极客程序设计
- 粉丝: 7525
- 资源: 3596
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功