//本人第一次发博客,有什么不对的地方,还请谅解
主要功能设计
| 1.图的初始化 | 由函数init()实现 |
| 2.学校景点介绍- | 简单循环输出 |
| 3.查看浏览路线 | 迪杰斯特拉算法实现 |
| 4.查看两景点之间的最短路径 | 弗洛伊德算法实现 |
| 5.景点信息查询 | 对应输出 |
| 6.更改图信息 | 图的基本操作 |
| 7.打印邻接矩阵 | 输出邻接矩阵的值 |
| 8.退出 | 退出系统 |
存储结构设计
class Vexsinfo {
public int ID;
public String name;
public String introduction;
public boolean isVisited;
public Vexsinfo(int id,String name, String a)
{
this.ID=id;
this.name=name;
this.introduction=a;
this.isVisited=false;
}
}
class MGraph/*图结构信息,邻接矩阵表示*/ {
public Vexsinfo[]vexs;/*顶点信息*/
public int [][]arcs;/*邻接矩阵,用整型值表示权值*/
public int arcNum;/*边数*/
public int vexNum;/*顶点数*/
public MGraph(int maxVexsNum,int maxsize) {
this.vexs=new Vexsinfo[maxVexsNum];
this.arcs=new int[maxsize][maxsize];
this.arcNum=maxVexsNum;
this.vexNum=maxsize;
init();
}
}
详细设计
/*显示景点所有信息景点*/
public void introduceCompus()/*1.校园简介,显示各地点的编号`名称和简介*/
{
System.out.format("\n\n%-6s%-30s%s\n","编号","景点名称","简介");
System.out.print(" \n");
for(int i=0;i<this.vexNum;i++)
System.out.format("%-6d%-30s%s\n",this.vexs[i].ID,this.vexs[i].name,this.vexs[i].introduction);
System.out.print(" \n");
}
/*查看浏览线路 */
public void browsePath()/*显示从给定景点出发,到其他景点的最短路径 */
{
/*迪杰斯特拉算法,求从顶点v0到其余顶点的最短路径p[][]及其带权长度d[v](最短路径的距离)
* P[][]数组用于存放两顶点间是否有通路标志。若p[v][w]==1,则w是从v0到v的最短路径上的顶点*/
int min,t=0,v0; //v0为起始景点编号
int []d=new int[35];
int [][]p=new int[35][35];
System.out.print("\n请输入一个起始景点编号");
Scanner sc=new Scanner(System.in);
v0=sc.nextInt();
System.out.print("\n\n");
while(v0<0||v0>this.vexNum)
{
System.out.print("\n你所输入的景点编号不存在");
System.out.print("\n请重新输入");
v0=sc.nextInt();
}
for(int v=0;v<this.vexNum;v++)
{
this.vexs[v].isVisited=false; //初始化各顶点访问标志
d[v]=this.arcs[v0][v]; //v0到各顶点v的权值赋值给d[v]
/*初始化p[][]数组,各顶点间的路径全部设置为空路径0*/
for(int w=0;w<this.vexNum;w++)
p[v][w]=0;
if(d[v]<1000) //v0到v有边相连,修改p[v][v0]的值为1
{
p[v][v0]=1;
p[v][v]=1; //各顶点自己到自己要连通
}
}
d[v0]=0; //自己到自己的权值为0
this.vexs[v0].isVisited=true; //v0的访问标志设为true,v属于s集
/*对其余vexNum-1个顶点w,依次求v到w的最短路径*/
for(int i=1;i<this.vexNum;i++)
{
min=1000;
/*在未被访问的顶点中,查找与v0最近的顶点v*/
for(int w=0;w<this.vexNum;w++)
if(!this.vexs[w].isVisited&&d[w]<min)
{
t=w;
min=d[w];
}
this.vexs[t].isVisited=true;//v的访问标志设置为1,v属于s集
/*修改v0到其余各顶点w的最短路径权值d[w]*/
for(int w=0;w<this.vexNum;w++)
/*若w不属于s,且v到w有边相连*/
if(!this.vexs[w].isVisited&&(min+this.arcs[t][w]<d[w]))
{
d[w]=min+this.arcs[t][w];//修改v0到w的权值d[w]
/*所有v0到vde最短路径上的顶点x,都是v0到w的*/
for(int x=0;x<this.vexNum;x++)
p[w][x]=p[t][x];/*最短路径上的顶点*/
p[w][w]=1;
}
}
for(int v=0;v<this.vexNum;v++)/*输出v0到其他顶点v的最短路径*/
{
if(v!=v0)
System.out.print(this.vexs[v0].name);//输出景点v0的景点名
/*对图中每个顶点w,试探w是否是v0到v的最短路径上的顶点*/
for(int w=0;w<this.vexNum;w++)
{
/*若w是,且w不等于v0,则输出该景点*/
if(p[v][w]==1&&w!=v0&&w!=v)
System.out.print("--->"+this.vexs[w].name);
}
System.out.print("--->"+this.vexs[v].name);
System.out.print("\t总路线长为"+d[v]+"米\n\n");
}
}
public void showShortestPath()
{
/*用floyd算法,求各对顶点v和w间的最短路径p[][][]及其带权长度d[v][w]
* 若p[v][w][u]==1,则u是v到w的当前求得的最短路径上的顶点*/
int j,k;
int [][]d=new int [23][23];
int [][][]p1=new int [23][23][23];
/*初始化各对顶点v,w之间的起始距离d[v][w]及p[v][w][]数组*/
for(int v=0;v<this.vexNum;v++)
for(int w=0;w<this.vexNum;w++)
{
d[v][w]=this.arcs[v][w];//d[v][w]中存放v至w间初始权值
/*初始化最短路径p[v][w][]数组,第3分量全部清0*/
for(int u=0;u<this.vexNum;u++)
p1[v][w][u]=0;
if(d[v][w]<1000)/*如果v至w之间有边相连*/
{
p1[v][w][v]=1;//v是v至w最短路径上的顶点
p1[v][w][w]=1;//w是v至w最短路径上的顶点
}
}
/*求v至w的最短路径距离*/
for(int u=0;u<this.vexNum;u++)
/*对任意顶点u,试探其是否为v至w最短路径上的顶点*/
for(int v=0;v<this.vexNum;v++)
for(int w=0;w<this.vexNum;w++)
/*从v经u到w的一条路径最短*/
if(d[v][u]+d[u][w]<d[v][w])
{
/*若i是v至u的最短路径上的点,或i是u至w最短路径上的点,则i是v至w的最短路径上的点*/
for(int i=0;i<this.vexNum;i++)
p1[v][w][i]=(p1[v][u][i]==1||p1[u][w][i]==1)?1:0;
}
System.out.print("\n请输入`出发点和目的地编号:");
Scanner sc=new Scanner(System.in);
k=sc.nextInt();
j=sc.nextInt();
System.out.print("\n\n");
while(k<0||k>this.vexNum||j<0||j>this.vexNum)
{
System.out.print("\n你所输入的景点编号不存在!");
System.out.print("\n请重新输入出发点和目的地编号:\n\n");
k=sc.nextInt();
j=sc.nextInt();
System.out.print("\n\n");
}
System.out.print(this.vexs[k].name);/*输出出发景点名称*/
for(int u=0;u<this.vexNum;u++)
if(p1[k][j][u]==1&&k!=u&&j!=u)/*输出最短路径上中间景点名称*/
System.out.print(this.vexs[u].name);
System.out.print(this.vexs[j].name);/*输出目的地景点名称*/
System.out.print("\n\n\n总长为"+d[k][j]+"米\n\n\n");
}
//景点信息查询
public void showVexsinfo(){
System.out.print("\n请输入要查询的景点编号:");
Scanner sc=new Scanner(System.in);
int k=sc.nextInt();
while(k<0||k>this.vexNum){
System.out.print("\n你所输入的景点编号不存在!");
System.out.print("\n请重新输入:");
k=sc.nextInt();
}
System.out.println("\n\n编号:"+this.vexs[k].ID);
System.out.println("\n\n景点名称:"+this.vexs[k].name);
System.out.println("\n\n介绍:"+this.vexs[k].introduction);
}
//查找景点在图中的序号
public int locateVex(int v){
for(int i=0;i<this.vexNum;i++){
if(v==this.vexs[i].ID)
return i;//找到,返回顶点序号i
}
return -1; //否则,返回-1
}
//更改图信息
public int changeGraph(){
int yourChoice;
Scanner sc=new Scanner(System.in);
do{
yourChoice=0;
System.out.print("\n-----------------------欢迎使用导游程序----------------------\n");
System.out.print("\n 请选择要完成的操作! \n\n");
System.out.print("\n 菜单选择 \n\n");
System.out.print(" 1.再次建图 2.删除结点 \n");
System.out.print(" 3.删除边 4.增加结点 \n");
System.out.print(" 5.增加边 6.更新信息 \n");
System.out.print(" 7.打印邻接矩阵 8.返回上一级 \n");
System.out.print("\n---------------------------------------------------------\n");
System.out.print("\n请输入你的选择:");
yourChoice=sc.nextInt();
switch(yourChoice){
case 1:recreate(); break;//重建图,调用(11)
case 2:delVex();break;//删除顶点
case 3:delArc();break;//删除边
case 4:addVex();break;//增加顶点
case 5:addArc();break;//增加边
case 6:modify();break;//更新图的信息,调用(16)
case 7:printMatrix();break;//输出邻接矩阵,调用(7)
case 8:return 1;//返回主菜单
default: System.out.print("输入选择不明确,请重新选择\n");break;
}
}while(yourChoice!=8);
return 1;
}
//重建构建图,以邻接矩阵表示
public int recreate(){//重建图,以图的邻接矩阵存储图
int j,m,n,v0,v1,distance;
System.out.print("请输入图的顶点数和边数:\n");
Scanner sc=new Scanner(System.in);
this.vexNum=sc.nextInt();
this.arcNum=sc.nextInt();
System.out.print("下面请输入景点的信息:\n");
for(int i=0;i<this.vexNum;i++){//构造顶点向量
System.out.print("请输入景点的编号:");
this.vexs[i].ID=sc.nextInt();
System.out.print("\n请输入景点的名称:");
this.vexs[i].name=sc.nextLine();
System.out.print("\n请输入景点的简介:");
this.vexs[i].introduction=sc.nextLine();
}
for(int i=0;i<this.arcNum;i++)//初始化邻接矩阵
for(j=0;j<this.arcNum;j++)
this.arcs[i][j]=1000;
System.out.print("下面请输入图的边的信息:\n");
for(int i=1;i<=this.arcNum;i++){
System.out.print("第"+i+"条边的起点 终点 长度为:");
v0=sc.nextInt();
v1=sc.nextInt();
distance=sc.nextInt();
m=locateVex(v0);
n=locateVex(v1);
if(m>=0&&n>=0){
this.arcs[m][n]=distance;
this.arcs[n][m]=this.arcs[m][n];
}
}
return 1;
}
public int delVex()/*删除地点(顶点)*/
{
if(this.vexNum<=0)
{
System.out.print("图中已无顶点");
return 1;
}
System.out.print("\n下面请输入你要删除的景点编号:");
Scanner sc=new Scanner(System.in);
int v=sc.nextInt();
while(v<0||v>this.vexNum)
{
System.out.print("\n输入错误!请重新输入");
v=sc.nextInt();
}
int m=locateVex(v);
if(m<0)
{
System.out.print("顶点“+v+”不存在!");
return 1;
}
/*对顶点信息所在顺序表进行删除m点的操作*/
for(int i=m;i<this.vexNum;i++)
{
this.vexs[i].ID=this.vexs[i+1].ID;
this.vexs[i].name=this.vexs[i+1].name;
this.vexs[i].introduction=this.vexs[i+1].introduction;
}
/*对原邻接矩阵,删除该顶点到其余顶点的邻接关系。分别删除相应的行和列*/
for(int i=m;i<this.vexNum-1;i++) /*行*/
for(int j=0;j<this.vexNum;j++) /*列*/
/*二维数组,从第m+1行开始依次往前移一行,即删除m行*/
this.arcs[i][j]=this.arcs[i+1][j];
for(int i=m;i<this.vexNum-1;i++) /*行*/
for(int j=0;j<this.vexNum;j++) /*列*/
/*二维数组,从第m+1行开始依次往前移一行,即删除m列*/
this.arcs[j][i]=this.arcs[j][i+1];
this.vexNum--;
System.out.print("顶点"+m+"删除成功!");
return 1;
}
public int delArc() /*删除边*/
{
if(this.arcNum<=0)
{
System.out.print("图中已边,无法删除。");
return 1;
}
System.out.print("\n下面请输入你要删除的边的起点和终点点编号:");
Scanner sc=new Scanner(System.in);
int v0=sc.nextInt();
int v1=sc.nextInt();
int m=locateVex(v0);
if(m<0)
{
System.out.print("顶点“+v0+”不存在!");
return 1;
}
int n=locateVex(v1);
if(n<0)
{
System.out.print("顶点“+v1+”不存在!");
return 1;
}
this.arcs[m][n]=1000;
this.arcs[n][m]=1000;
this.arcNum--;
System.out.print("边(“+v0+“,”+v1+”)删除成功!");
return 1;
}
public int addVex() /*添加景点(顶点)*/
{
System.out.print("请输入你要增加的结点信息:");
System.out.print("\n编号:");
Scanner sc=new Scanner(System.in);
this.vexs[this.vexNum].ID=sc.nextInt();
System.out.print("\n名称:");
this.vexs[this.vexNum].name=sc.nextLine();
System.out.print("\n简介:");
this.vexs[this.vexNum].introduction=sc.nextLine();
this.vexNum++;
/*对原邻接矩阵新增加的一行及一列进行初始化*/
for(int i=0;i<this.vexNum;i++)
{
this.arcs[this.vexNum-1][i]=1000;/*最后一行(新增的一行)*/
this.arcs[i][this.vexNum-1]=1000;/*最后一列(新增的一列)*/
}
return 1;
}
public int addArc() /*添加边*/
{
int m,n,distance;
System.out.print("\n请输入边的起点和终点编号,权值:");
Scanner sc=new Scanner(System.in);
m = sc.nextInt();
n = sc.nextInt();
distance = sc.nextInt();
while(m<0||m>this.vexNum||n<0||n>this.vexNum)
{
System.out.print("输入错误,请重新输入");
m = sc.nextInt();
n = sc.nextInt();
}
if(locateVex(m)<0)
{
System.out.print("此顶点“+m+”不存在");
return 1;
}
if(locateVex(n)<0)
{
System.out.print("此顶点“+n+”不存在");
return 1;
}
this.arcs[m][n]=distance;
this.arcs[n][m]=this.arcs[m][n];/*对称赋值*/
System.out.print("边(“+m+“,”+n+”)添加成功!");
return 1;
}
public int modify()/*更新图的部分信息,返回值:1*/{
System.out.print("\n下面请输入你要修改的景点的个数:\n");
Scanner sc=new Scanner(System.in);
int changenum=sc.nextInt();
while(changenum<0||changenum>this.vexNum){
System.out.print("\n输入错误!请重新输入");
changenum=sc.nextInt();
}
for(int i=0;i<changenum;i++){
System.out.print("\n请输入景点的编号:");
int m=sc.nextInt();
int t=locateVex(m);
System.out.print("\n请输入景点的名称:");
this.vexs[t].name=sc.nextLine();
System.out.print("\n请输入景点的简介:");
this.vexs[t].introduction=sc.nextLine();
}
System.out.print("\n下面请输入你要更新的边数");
changenum=sc.nextInt();
while(changenum<0||changenum>this.arcNum){
System.out.print("\n输入错误!请重新输入");
changenum=sc.nextInt();
}
System.out.print("\n下面请输入更新边的信息:\n");
for(int i=1;i<=changenum;i++){
System.out.print("\n修改的第"+i+"条边的起点、终点的长度为:");
int v0=sc.nextInt();
int v1=sc.nextInt();
int distance=sc.nextInt();
int m=locateVex(v0);
int n=locateVex(v1);
if(m>=0&&n>=0){
this.arcs[m][n]=distance;
this.arcs[n][m]=this.arcs[m][n];
}
}
System.out.print("图信息更新成功!");
return 1;
}
public void printMatrix() /*打印学校地图的邻接矩阵*/{
for(int i=0;i<this.vexNum;i++){
System.out.print("\n");
for(int j=0;j<this.vexNum;j++){
if(this.arcs[i][j]==1000)
System.out.print(" * ");
else
System.out.print(this.arcs[i][j]);
}
}
System.out.print("\n");
}
public void init ()/*通过初始化,一次性得到具有若干点的地图*/{
String []names={"学院侧门","音乐广场","西办公楼","东办公楼",
"西A、西B教学楼","东A、东B教学楼","实验楼",
"正阳餐厅","学生宿舍1-4栋",
"学生宿舍5-6栋",
"体育场","中心广场","学生宿舍10-12栋",
"学生宿舍7-9栋","小广场","晨曦餐厅","新力路",
"第二教学楼","图书馆、第二实验大楼","体育馆",
"霞光餐厅","学生宿舍13、14、17、18栋","学生宿舍15-16栋",};
String []introduces={"学院主路要进出口,离公交车站很近,
有93、703、511、54、305等多路公交车",
"音乐广场,学院大门","学院西办公楼,楼高6层",
"学院东办公楼,楼高6层","西A、西B教学楼,楼高5层",
"东A、东B教学楼,楼高5层","实验大楼,楼高6层",
"正阳餐厅,学生食堂","学生宿舍1-4栋,楼高6层",
"学生宿舍4-6栋,楼高6层","体育场",
"中心广场,在实验楼、体育场、晨曦餐厅附近",
"学生宿舍10-12栋,楼高6层",
"学生宿舍7-9栋,楼高6层","小广场,晨曦餐厅附近",
"晨曦餐厅、学生食堂","红区和蓝区之间的大门及通道",
"第二教学楼,楼高六层","图书馆、第二实验大楼",
"体育馆","霞光餐厅,学生食堂",
"学生宿舍13、14、17、18栋,楼高六层",
"学生宿舍15-16栋,楼高六层"};
for(int i=0;i<this.vexNum;i++)/*依次设置图的各顶点信息*/{
this.vexs[i]=new Vexsinfo(i,names[i],introduces[i]);
}
for(int i=0;i<this.vexNum;i++)/*先初始化图的邻接矩阵*/
for(int j=0;j<this.vexNum;j++)
this.arcs[i][j]=1000;/*1000表示无边*/
this.arcs[0][1]=185;this.arcs[0][11]=171;this.arcs[1][2]=69;
this.arcs[1][3]=69;this.arcs[1][6]=180;this.arcs[1][16]=196;
this.arcs[2][3]=86;this.arcs[2][4]=85;this.arcs[3][5]=85;
this.arcs[4][5]=120;this.arcs[4][6]=65;this.arcs[4][16]=170;
this.arcs[5][6]=65;this.arcs[6][7]=302;this.arcs[6][8]=220;
this.arcs[6][9]=246;this.arcs[7][8]=97;this.arcs[7][9]=97;
this.arcs[9][10]=219;this.arcs[10][11]=176;this.arcs[10][12]=244;
this.arcs[11][12]=100;this.arcs[11][13]=79;this.arcs[11][14]=126;
this.arcs[12][14]=69;this.arcs[13][14]=106;this.arcs[14][15]=142;
this.arcs[16][17]=73;this.arcs[16][20]=246;this.arcs[16][22]=72;
this.arcs[17][18]=163;this.arcs[18][19]=143;this.arcs[19][20]=90;
this.arcs[20][21]=161;this.arcs[21][22]=150;
for(int i=0;i<this.vexNum;i++)/*邻接矩阵是对称矩阵,对称赋值*/
for(int j=0;j<this.vexNum;j++)
this.arcs[j][i]=this.arcs[i][j];
}
主程序设计
import java.util.*;
public class Teat {
public static void main(String[] args) {
// TODO Auto-generated method stub
int yourChoice;
String iSExit="n";
MGraph campus=new MGraph(23,23);
Scanner in=new Scanner (System.in);
do {
yourChoice=0;
System.out.print("\n--------------------------------欢迎使用校园导游系统----------------------------------\n");
System.out.print("\n 欢迎来到电子科技大学成都学院!\n\n");
System.out.print("\n 菜 单 选 择\n\n ");
System.out.print("\n 1.学校景点介绍 2.查看游览路线\n\n");
System.out.print("\n 3.查询景点间最短路径 4.景点信息查询\n\n");
System.out.print("\n 5.更改图信息 6.打印领接矩阵\n\n");
System.out.print("\n 7.退出\n");
System.out.print("\n---------------------------------------------------------------------------------\n");
System.out.print("\n请输入你的选择\n");
yourChoice=in.nextInt();
switch(yourChoice)
{
case 1:campus.introduceCompus(); break;
case 2:campus.browsePath(); break;
case 3:campus.showShortestPath(); break;
case 4:campus.showVexsinfo(); break;
case 5:campus.changeGraph(); break;
case 6:campus.printMatrix(); break;
case 7:
System.out.print("您确定要退出系统么?(Y/N):");
iSExit=in.nextLine();
if(iSExit=="Y"||iSExit=="y")
System.exit(0);
else
iSExit="n";
break;
default:
System.out.print("输入选择不明确,请重新输入\n");
break;
}
}
while(yourChoice!=7||iSExit=="n");
in.close();
}
}
本文介绍了校园导航系统的数据结构设计,包括存储结构的设计思路,详细的实现方案,以及主程序的构建过程。

7379





