一.问题分析
算法设计
采用
邻接表
存储
有向图
,设计算法判断任意两个顶点间是否存在路径。
1.邻接表
表节点
顶点节点
无向图
有向图
2.图的遍历
深度优先遍历
二.概要设计
最好一个类创建一个文件
1.VNode类
定义顶点节点,存放顶点的名称或相关数据,指针。
package Study;
public class VNode<T> { //顶点结点类型定义
T data; //存储顶点的名称或其相关信息
ArcNode firstArc; //指向顶点Vi的第一个邻接点的边结点
public VNode() {
data=null;firstArc=null;
}
}
2.ArcNode类
定义边节点,存放邻接点的序号,权重,指针。
package Study;
public class ArcNode { //边结点的类型定义
int adjVex; //存放邻接的点的序号
ArcNode nextArc; //指向Vi下一个邻接点的边结点
int weight;//权值
public ArcNode(){
adjVex=0;weight=0;nextArc=null;
}
}
3.ALGraph类
定义图,包含顶点数组,图的顶点数,弧数和封装的函数
封装的函数
CreateLink()
创建有向图的邻接表
LocateVex()
查找顶点,找到后返回其在顶点数组中的索引号,若不存在,返回-1
hasPath()
调用LocateVex()查找需判断路径的起始点和终止点,标记每一个节点的状态(是否被访问),调用dfs()
dfs()
实现深度优(DFS),用于判断两个顶点之间是否存在路劲
DisplayAdjList()
输出有向图的邻接表
package Study;
import java.util.Scanner;
public class ALGraph<T> { //图的邻接表数据类型
protected final int MAXSIZE=10;
protected VNode[] adjList; //顶点结点信息
int n,e;//图的顶点数和弧数
public ALGraph(){
adjList=new VNode[MAXSIZE];
}
public void CreateLink(){ //创建无向图的邻接表
int i,j,k;
T v1,v2;
ArcNode s;
String str;
Scanner sc=new Scanner(System.in);
System.out.println("请输入图的顶点数及边数");
System.out.print("顶点数n="); n=sc.nextInt();;
System.out.print("边数e=");e=sc.nextInt();
System.out.println("请输入图的顶点信息:");
str=sc.next();
for(i=0;i<n;i++){
adjList[i]=new VNode();
adjList[i].data=str.charAt(i);//构造顶点信息
adjList[i].firstArc=null;
}
System.out.println("请输入图的边的信息:");
for(k=0;k<e;k++){
System.out.print("请输入第"+(k+1)+"条边的两个端点:");
str=sc.next();//输入一条边的两个顶点
v1=(T) (Object)str.charAt(0);
v2=(T) (Object)str.charAt(1);
//确定两个顶点在图G中的位置
i=LocateVex(v1);j=LocateVex(v2);
if(i>=0&&j>=0){
s=new ArcNode();
s.adjVex=j;
s.nextArc=adjList[i].firstArc;
adjList[i].firstArc=s;
}
}
}
//在图中查找顶点v,找到后返回其在顶点数组中的索引号,若不存在,返回-1
public int LocateVex(T v){
int i;
for(i=0;i<n;i++)
if(adjList[i].data==v)return i;
return -1;
}
// 判断任意两个顶点间是否存在路径
public boolean hasPath(T v1, T v2) {
int start = LocateVex(v1);//获取起始点在顶点数组中的索引
int end = LocateVex(v2);//获取终止点在顶点数组中的索引
if (start == -1 || end == -1) {
// 顶点不存在
return false;
}
boolean[] visited = new boolean[n];//创建一个布尔数组用于标记顶点的访问状态
return dfs(start, end, visited);//调用dfs
}
private boolean dfs(int current, int end, boolean[] visited) {
if (current == end) {
return true; // 如果当前节点是目标节点,则找到路径
}
visited[current] = true;//标记当前节点已被访问
ArcNode p = adjList[current].firstArc;//获取当前节点的邻接表的第一个边界点
while (p != null) {
//对于当前节点的每一个边节点,如果没有被访问过,且从他开始存在路径到目标终止顶点
//则说明存在从当前顶点到目标终点的路径,返回true
if (!visited[p.adjVex] && dfs(p.adjVex, end, visited)) {//递归调用
return true;
}
p = p.nextArc;//移动到下一个邻接点
}
return false;//没有找到路径,返回false
}
public void DisplayAdjList(){ //在屏幕上显示图的邻接表表示
int i;
ArcNode p;
System.out.println("图的邻接表表示:");
for(i=0;i<n;i++){
System.out.print("\n "+adjList[i].data);
p=adjList[i].firstArc;
while(p!=null){
System.out.print("-->"+p.adjVex);p=p.nextArc;
}
}
System.out.println();
}
}
4.测试类-Main
package Study;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
ALGraph<Character> G=new ALGraph<>();//创建对象
G.CreateLink();//构建有向图
G.DisplayAdjList();//输出有向图
//键盘输入需要查找路径的开始节点与结束节点
Scanner scanner = new Scanner(System.in);
System.out.print("请输入开始节点:");
char startNode = scanner.next().charAt(0);
System.out.print("请输入结束节点:");
char endNode = scanner.next().charAt(0);
boolean hasPath = G.hasPath(startNode, endNode);//判断路径是否存在
if (hasPath) {//输出结果
System.out.println("存在路径从顶点 " + startNode + " 到顶点 " + endNode);
} else {
System.out.println("不存在路径从顶点 " + startNode + " 到顶点 " + endNode);
}
}
}