/**
* @author shany
* @date 2018年8月27日 上午8:50:12
* @version V1.0
*/
package shany;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class DjstSF {
// 设置当前图的形式(有权图,无权图),默认为无权图false
static boolean direction = false;
// 存储所有的节点
static List<String> all_list = new ArrayList<>();
// 存储所有路径和之间的距离
static Map<String, Integer> data_map = new HashMap<String, Integer>();
// 当前记录的路径和权值
static Map<String, Integer> use_map = new HashMap<>();
// 开始节点
static String start_seat;
// 结束节点
static String end_seat;
// 用于测试
// static int num = 0;
// 有权无权图都适用
public void addNum(String key) {
// 判断传入的key是否为空
key = key == null ? start_seat : key == "" ? start_seat : key;
Set<String> set = data_map.keySet();
// 新的value应该加上的值
int date = use_map.containsKey(key) ? use_map.get(key) : 0;
// 获取key的末尾节点值
String key_sta = key.indexOf("-") != -1 ? key.substring(
key.lastIndexOf("-") + 1, key.length()) : key;
// 循环遍历data_map里面的值
for (String str : set) {
// 先获取对应value值
int val = data_map.get(str);
// 以下三行用于测试
// System.out.println("——————————");
// System.out.println("第" + ++num + "次:");
// System.out.println("key=" + key + " " + "str=" + str + " --"+
// val);
String ss[] = str.split("-");
// 判断传入的key中是否包含ss[1]
if (!(new ArrayList<String>(Arrays.asList(key.split("-")))
.contains(ss[1]))) {
// 如果是有权图,且ss[0]和key的尾部对应
if (direction && ss[0].equals(key_sta)) {
// System.out.println("youquan: str=" + str);//用于测试
use_map.put(add_new_key(key, str), date + val);// 将新key和value插入到use_map中
use_map.remove(key);// 当有新key插入时,就可以删除老key了,重复删除不会有异常
} else if (!direction
&& (ss[0].equals(key_sta) || ss[1].equals(key_sta))) {
// 无权图要对ss[0]和ss[1]同时判断,同时key==初始点要做额外判断
if (key == start_seat
|| !(new ArrayList<String>(Arrays.asList(key
.split("-"))).contains(ss[0]))) {
// System.out.println("wuquan: str=" + str);//用于测试
use_map.put(add_new_key(key, str), date + val);
use_map.remove(key);// 当有新key插入时,就可以删除老key了,重复删除不会有异常
}
}
// System.out.println("第" + ++num + "次:");//用于测试
// input_map(); //用于测试
}
}
}
// 对老的key,和新加入的key进行组合,输出新的要插入的key。
public String add_new_key(String old_key, String ext) {
if (old_key.indexOf(ext.split("-")[0]) != -1)
return old_key + "-" + ext.split("-")[1];
else if (old_key.indexOf(ext.split("-")[1]) != -1)
return old_key + "-" + ext.split("-")[0];
// 用于use_map传入到addNum的key为null(这个主要防止出现意外错误)时
return old_key + "-" + ext;
}
// 测试时输出use_map的遍历,用于观察(测试、观察用)
public void input_map() {
for (Map.Entry<String, Integer> entry : use_map.entrySet()) {
String key = entry.getKey().toString();
System.out.println("key:" + key + " ——" + use_map.get(key));
}
}
// 循环这个路线
public void roll_map() {
// 记录改变的key数量
int sure_end = 0;
Map<String, Integer> temp_map = new HashMap<String, Integer>();
temp_map.putAll(use_map);
// 第一次use_map为null时调用此if
if (temp_map == null || temp_map.size() == 0) {
// System.out.println("roll_map:null");
addNum(null);
sure_end++;
} else {
// 是否全部走完,防止死循环
for (Map.Entry<String, Integer> entry : temp_map.entrySet()) {
String key = entry.getKey().toString();
if (key.indexOf(end_seat) == -1) {
// System.out.println("roll_map:" + key);//用于测试
// 调用函数,尝试更新路径
addNum(key);
}
}
}
// 判断在经过一轮循环后use_map是否变化,如果没变化就停止,防止死循环
for (Map.Entry<String, Integer> entry : use_map.entrySet()) {
String key = entry.getKey().toString();
// 判断有无变化
if (temp_map.get(key) != use_map.get(key))
sure_end++;
}
// 当有一个key值改变时
if (sure_end == 0)
// 结束递归
return;
else
// 继续递归
roll_map();
}
// 获取最小路径的key
public String min_key() {
int num = 0;
String result_key = "";
for (Map.Entry<String, Integer> entry : use_map.entrySet()) {
String key = entry.getKey().toString();
// 当路径长度为0,或者路径比最短路径小时,替换
if (("".equals(result_key) && num == 0) || use_map.get(key) < num) {
result_key = key;
num = use_map.get(key);
}
}
return result_key;
}
// 判断能否添加该key
public boolean sure_add(String key) {
String kk[] = key.split("-");
if (kk.length >= 2) {
String temp = "";
for (int i = 0; i < kk.length - 2; i++) {
temp += kk[i] + "-";
}
temp += kk[kk.length - 1] + "-" + kk[kk.length - 2];
return !use_map.containsKey(temp);
} else {
return !use_map.containsKey(key);
}
}
// 循环加入 key形式"A-B",其中A和B都是节点
public void add_map(String key, Integer value) {
// 加入数据map
data_map.put(key, value);
//
all_list.add(key.split("-")[0]);
all_list.add(key.split("-")[1]);
}
// 主函数
public static void main(String[] args) {
// key形式"A-B",其中A和B都是节点,value 是长度形式添加到data_map中
// 设置开始节点start_seat,和结束节点end_seat,设置是否是有权无权(默认false,无权图)direction
// 运行roll_map()函数即可
DjstSF df = new DjstSF();
data_map.put("1-2", 2);
data_map.put("1-3", 12);
data_map.put("1-5", 3);
data_map.put("2-4", 6);
data_map.put("2-3", 3);
data_map.put("4-3", 4);
data_map.put("3-5", 5);
data_map.put("5-4", 2);
data_map.put("5-6", 4);
data_map.put("4-6", 15);
start_seat = "1";
end_seat = "6";
direction = true;
df.roll_map();
System.out.println("最小的是" + df.min_key());
}
}
备注:我当时测试时用的是有权图测试的,无权图也许会存在一些瑕疵。。。,抽空我再测试下无权图,图有空再配吧。。。