/**
* @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());
}
}
備註:我當時測試時用的是有權圖測試的,無權圖也許會存在一些瑕疵。。。,抽空我再測試下無權圖,圖有空再配吧。。。