首先创建一个图类,写入方法,读取文件格式为邻接矩阵;
package Interface;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
public class Graph {
public String[] land;
public String tralvist;
public String[] info;
public int vexnum;
public int[][] arcs;
public int[][] distance;
public String[][] path;
public Graph() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("D:\\旅游景点\\景点.txt", StandardCharsets.UTF_8));
vexnum = Integer.parseInt(br.readLine());
land = new String[vexnum];
info = new String[vexnum];
for(int i=0;i<vexnum;i++){
String s = br.readLine();
String[] s1 = s.split(":");
land[i]=s1[0];
info[i]=s1[1];
}
arcs = new int[vexnum][vexnum];
for (int p = 0; p < vexnum; p++) {
String s = br.readLine();
String[] s1 = s.split(" ");
for (int q = 0; q < vexnum; q++) {
arcs[p][q] = Integer.parseInt(s1[q]);
}
}
tralvist = land[0];
br.close();
}
//增加
public void add(String s, String s0,String s1) throws IOException {
vexnum++;
land = Arrays.copyOf(land, land.length + 1);
info = Arrays.copyOf(info, info.length + 1);
land[vexnum - 1] = s;
info[vexnum - 1] = s0;
String[] a = s1.split(" ");
int[][] temp = new int[vexnum][vexnum];
for (int i = 0; i < vexnum - 1; i++) {
for (int j = 0; j < vexnum - 1; j++) {
temp[i][j] = arcs[i][j];
}
}
for (int i = 0; i < vexnum; i++) {
temp[vexnum - 1][i] = Integer.parseInt(a[i]);
temp[i][vexnum - 1] = Integer.parseInt(a[i]);
}
arcs = temp;
updata();
System.out.println("----------添加成功");
}
//删除
public void delete(int index) throws IOException {
if (index==vexnum-1){
vexnum--;
updata();
return;
}
for (int i = index + 1; i < vexnum; i++) {
land[i - 1] = land[i];
}
land = Arrays.copyOf(land, land.length - 1);
for (int i = index + 1; i < vexnum; i++) {
arcs[i - 1] = arcs[i];
}
for (int i = index + 1; i < vexnum; i++) {
for (int j = 0; i < vexnum; j++) {
arcs[i - 1][j] = arcs[i][j];
}
}
vexnum--;
updata();
System.out.println("-------删除成功");
}
// 找到用户输入位置的节点
public void search(int i){
System.out.println("-------景点名称"+land[i-1]);
System.out.println("-------景点介绍:"+info[i-1]);
}
// 通过节点名称找位置
public int search0(String s){
int i=0;
for(String s1 : land){
if(s.equals(s1)){
return i;
}
i++;
}
return -1;
}
// 更改景点介绍
public void reset(int index,String s) throws IOException {
info[index-1] = s;
updata();
}
// 找两点的最短路径并输出
public void searchshortestpath(int index,int end){
folyd();
String s = land[index];
String s1 = path[index][end];
System.out.print("到"+land[end]+"的最短路径为:"+s);
while (s1!=land[end]){
System.out.print("--->"+s1);
int index1=search0(s1);
s1=path[index1][end];
}
System.out.println("--->"+land[end]);
System.out.println("-----距离:"+distance[index][end]+"km");
}
// 简单路径
public String searchshortestpath1(int index,int end){
folyd();
String s = land[index];
String s1 = path[index][end];
while (s1!=land[end]){
s+=" "+s1;
int index1=search0(s1);
s1=path[index1][end];
}
return s;
}
// 数据更新
public void updata() throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\旅游景点\\景点.txt",StandardCharsets.UTF_8));
String w = "";
String m = String.valueOf(vexnum)+"\n";
bw.write(m);
for (int i = 0; i < vexnum; i++) {
w = land[i]+":"+info[i]+ "\n";
bw.write(w);
}
for (int i = 0; i < vexnum; i++) {
w = "";
for (int j = 0; j < vexnum; j++) {
w += arcs[i][j];
w +=" ";
}
w += "\n";
bw.write(w);
}
bw.close();
}
// 弗洛伊德找所有点的最短路径和距离
public void folyd() {
distance=new int[vexnum][vexnum];
path = new String[vexnum][vexnum];
// 初始化路径和距离
for (int i=0;i<vexnum;i++){
for (int j=0;j<vexnum;j++){
distance[i][j] = arcs[i][j];
path[i][j]=land[j];
}
}
for (int i = 0; i < vexnum; i++) {
// i 作为中转节点
for (int j=0;j<vexnum;j++){
// j 作为起始节点
for (int k=0; k < vexnum; k++) {
// k 作为终止节点
if (distance[j][i] != -1 && distance[i][k] != -1) {
// 如中转点无法到达起始和终点
int newDistance = distance[j][i] + distance[i][k];
if (newDistance < distance[j][k] || distance[j][k] == -1) {
distance[j][k] = newDistance;
path[j][k] = path[j][i];
}
}
}
}
}
}
public void DFS0(int start,int end){
boolean[] flag = new boolean[vexnum];
String path0 = land[start];
int dt =0;
System.out.println("-----到"+land[end]+"的所有简单路径如下:");
DFS(start,end,flag,path0,dt);
}
public void DFS(int start,int end,boolean[] flag,String path0,int dt){
if (start==end){
System.out.println(path0);
System.out.println("-----距离:"+dt+"km");
}
flag[start]=true;
for (int i=0;i<vexnum;i++){
if (arcs[start][i]>0&&!flag[i]){
DFS(i,end,flag,path0+"-->"+land[i],dt+arcs[start][i]);
}
}
flag[start]=false;
}
public void perm(int[] br, int start, int end, ArrayList<int[]> path){
if (start==end){
path.add(Arrays.copyOf(br, br.length));
}
else {
int temp;
for (int i = start; i <= end; i++) {
temp = br[i];
br[i] = br[start];
br[start] = temp;
perm(br, start + 1, end, path);
temp = br[i];
br[i] = br[start];
br[start] = temp;
}
}
}
}
然后写出Main类
package Interface;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
String order;
Graph g = new Graph();
menu:
while(true){//
Home.menu();
order=Input.validInput("1", "2", "3", "4", "5");
switch (order) {
case "*":break menu;
case "1":
menu1:
while (true) {
Home.jiemian1(g);
order = Input.validInput(g.vexnum+1);
switch (order) {
case "*":break menu;
case "#":break menu1;
case "a":
order = Input.contentInput("景点");
String ifo = Input.contentInput("介绍");
String dis = Input.contentInput("与各个景点间的距离");
g.add(order,ifo,dis);
break menu1;
default:
int index = Integer.parseInt(order);
g.search(index);
System.out.println("---------更改请按1");
System.out.println("---------删除请按2");
System.out.println("---------到达请按3");
System.out.println("---------返回请按#");
order=Input.validInput("1","2","3","#");
if (order.equals("#"))
break menu1;
else if (order.equals("1")){
order = Input.contentInput("更改");
g.reset(index, order);
}
else if (order.equals("2")){
g.delete(index-1);
}
else {
g.tralvist = g.land[index-1];
}
}
}
break;
case "2":
menu2:
while (true){
Home.jiemian2(g);
order = Input.validInput("#","*");
if (order.equals("#"))
break menu2;
break menu;
}
break ;
case "3":
menu3:
while (true){
Home.jiemian3(g);
order = Input.validInput(g.vexnum+1);
if (order.equals("#"))
break menu3;
Home.jiemian31(g,order);
System.out.println("-----输入#号返回");
order =Input.validInput("#");
}
break ;
case "4":
menu4:
while (true){
Home.jiemian4(g);
order = Input.validInput(g.vexnum+1);
if (order.equals("#"))
break menu4;
String end =Input.excludeInput(g.vexnum,order);
g.DFS0(Integer.parseInt(order)-1,Integer.parseInt(end)-1);
g.searchshortestpath(Integer.parseInt(order)-1,Integer.parseInt(end)-1);
System.out.println("-----输入#号返回");
order =Input.validInput("#");
}
break ;
case "5":
menu5:
while (true){
Home.jiemian5(g);
order =Input.validInput("#");
if (order.equals("#"))
break menu5;
}
break ;
}
}
}
}
同时因为有对输出和界面的要求,写个input类矫正输入,home类规范界面
package Interface;
import java.util.Scanner;
public class Input {
public static String validInput(String... strings) throws InterruptedException {
Scanner scanner = new Scanner(System.in);
while (true) {
String str = "";
if (scanner.hasNextLine())
str = scanner.nextLine();
else safeExit();
str = str.trim();
for (String data : strings) {
if (data.equals(str)) {
return data;
}
}
System.out.print("输入无效,请重新输入,回车确认:");
}
}
public static String validInput(int maxRange) throws InterruptedException {
String[] strings = new String[maxRange +3];
int i;
for (i = 0; i < maxRange; ++i) {
strings[i] = "" + (i+1);
}
strings[maxRange] = "*";
strings[maxRange +1] = "#";
strings[maxRange+2] = "a";
return validInput(strings);
}
public static String excludeInput(int maxRange, String... invalidStrings) throws InterruptedException {
String[] strings = new String[maxRange +2];
int i;
for (i = 0; i < maxRange; ++i) {
strings[i] = "" + i;
}
strings[maxRange] = "*";
strings[maxRange +1] = "#";
Scanner scanner = new Scanner(System.in);
outer:
while (true) {
String str = "";
if (scanner.hasNextLine())
str = scanner.nextLine();
else safeExit();
str = str.trim();
for (String invalidStr : invalidStrings) {
if (str.equals(invalidStr)) {
System.out.print("输入无效,请重新输入,回车确认:");
continue outer;
}
}
for (String data : strings) {
if (data.equals(str)) {
return data;
}
}
System.out.print("输入无效,请重新输入,回车确认:");
}
}
public static String contentInput(String str) throws InterruptedException {
System.out.println("请输入" + str + "内容 :");
Scanner scanner = new Scanner(System.in);
if (scanner.hasNextLine())
str = scanner.nextLine();
else safeExit();
str = str.trim();
if (str.isEmpty()) str = "未检测到输入内容";
return str;
}
private static void safeExit() throws InterruptedException {
System.out.println("--------正在退出");
Thread.sleep(1500);
System.out.println("-----感谢您的使用");
System.exit(0);
System.out.println();
}
}
package Interface;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class Home {
public static void menu() throws IOException, InterruptedException {
System.out.println("--------旅游区景点导游系统 V 1.0------");
System.out.println("\n----欢迎使用本系统---");
System.out.println("\n1.---景点信息查询与编辑---");
System.out.println("\n2.-----当前位置及相邻景点----");
System.out.println("\n3.--景点最短路径查询--");
System.out.println("\n4.--景点简单路径查询--");
System.out.println("\n5.--最佳景点观赏路线--");
System.out.println("\n-------输入ctr+D退出系统");
System.out.println("\n\n------请选择:");
}
public static void jiemian1(Graph g) throws IOException {
allspot(g);
System.out.println("-------请选择要查看和编辑的景点");
System.out.println("-------添加请按”a“");
System.out.println("-------返回请按”#“");
System.out.println("-------退出请按“*”");
}
public static void jiemian2(Graph g){
System.out.print("-----当前景点:");
System.out.println(g.tralvist);
System.out.println("相邻景点及距离:");
int index=g.search0(g.tralvist);
for (int i=0;i<g.vexnum;i++){
if (g.arcs[index][i]>0){
System.out.print(g.land[i]+"------距离:");
System.out.println(g.arcs[index][i]+"km");
}
}
System.out.println("-----输入#号返回");
}
public static void jiemian3(Graph g) throws IOException {
allspot(g);
System.out.println("------请选择查询景点");
System.out.println("-----输入#号返回");
}
public static void jiemian31(Graph g,String order){
int index = Integer.parseInt(order)-1;
for (int i=0;i<g.vexnum;i++){
if (i==index)
continue;
g.searchshortestpath(index,i);
}
}
public static void jiemian4(Graph g) throws IOException {
allspot(g);
System.out.println("------请选择需要查询的两个景点(回车后输入下一个景点)");
System.out.println("-----输入#号返回");
}
public static void jiemian5(Graph g) throws IOException, InterruptedException {
allspot(g);
System.out.println("------请选择需要查询的景点");
System.out.println("-----输入#号返回");
String order = Input.validInput(g.vexnum+1);
youlan(g, Integer.parseInt(order)-1);
}
public static void youlan(Graph g,int start){
System.out.println("---------推荐游览路线");
ArrayList<int[]> path = new ArrayList<>();
int[] br =new int[g.vexnum];
for (int i=0;i<g.vexnum;i++){
br[i]=i;
}
g.perm(br,0,g.vexnum-1,path);
int [] re;
int minindex=Integer.MAX_VALUE;
String minpath = "";
g.folyd();
for (int i=0;i<path.size();i++){
re = path.get(i);
if (re[0]==start) {
int min = 0;
String mp = "";
for (int j = 0, k = j + 1; j < g.vexnum-1; j++) {
min += g.distance[re[j]][re[k]];
mp += g.searchshortestpath1(re[j], re[k]) + " ";
}
if (minindex > min) {
minindex = min;
minpath = mp + g.land[path.get(i)[g.vexnum - 1]];
}
}
}
System.out.println("------"+minpath);
System.out.println("------所需路程"+minindex+"km");
System.out.println();
System.out.println();
System.out.println("-----输入#号返回");
}
public static void allspot(Graph g) throws IOException {
System.out.println("------所有景点-------");
for (int i=0;i<g.vexnum;i++){
System.out.print("-------"+(i+1));
System.out.println("."+g.land[i]);
}
}
}
以下是我的文件格式
第一行是景点个数
下面的景点名称及介绍
最后的矩阵为邻接矩阵,表示各节点间的距离。