邻接表:
dfs4(a,start,end,visited,stack,-1)//递归
dfs5(a,start,end);//非递归
邻接矩阵:(可以直接用矩阵数据计算路径长度)
dfs6(m,start,end,visited,stack,-1);//递归
dfs7(m,start,end);//非递归
递归的思路来自https://blog.csdn.net/hackersuye/article/details/79044555
非递归是自己做的
大家可以试试。
邻接表和邻接矩阵的写法是来自《天勤高分笔记数据结构》。
邻接表
package dfs;
class AGraph{
int n;
int e=0;
VNode adjlist[];
public AGraph(int n) {
super();
this.n = n;
adjlist=new VNode[n];
}
}
package dfs;
class ArcNode{
int adjvex; ArcNode nextarc;
int weight;//weight就是adjlist[i]->adjvex的权重
//对应于邻接矩阵的权重m[i][adjvex]
AGraph a;//记录边数时,需要图a
int edge_type=0;//初始化为回边(P99.8)
public ArcNode(int adjvex, AGraph a) {
super();
this.adjvex = adjvex;
this.a = a;
a.e+=1;
}
public ArcNode() {
}
public ArcNode (int adjvex){
this.adjvex=adjvex;
};
}
package dfs;
class VNode{//邻接矩阵的顶点也可以用这个
ArcNode firstarc;
char info;
int level;//对应于99.8,对每个点,都要有层级
public VNode(char info) {
this.info = info;
}
int ini=1;//用于利用邻接表非递归输出全部路径的DFS
//在该次应该指向链接表的哪一个arc
//初始值为1,即firstarc;若大于1,不停地取nextarc,
//直到找到对应的 第ini边
}
邻接矩阵
package dfs;
public class VertexType {
int no;
int ini=0;//用于利用邻接矩阵非递归输出全部路径的DFS
//这里的ini是指向的顶点数字(因为用邻接矩阵总要从后向前遍历)
//不是VNode里面的第几个
}
package dfs;
public class MGraph {
int n;
int e=0;//n为顶点数,e为边数
//int edges[][];
VertexType vex[];
int edges[][];
public MGraph(int n) {
this.n = n;
edges=new int[n][n];
vex=new VertexType[n];
for(int i=0;i<vex.length;i++)
vex[i]=new VertexType();
}
public void set(int i,int j)
{
edges[i][j]=1;
//如果是无向图的话
edges[j][i]=1;
e+=2;
}
}
4个方法
public static void dfs4(AGraph a,int start,int end,
int visited[],int stack[],int top)
{ visited[start]=1;
stack[++top]=start;
if(start==end) {
System.out.println("成功");
for(int i=0;i<=top;i++)
System.out.print(stack[i]+" ");
System.out.println("");//出栈
top--;
visited[end]=0;
//visited[stack[top]]=0;top--;
return;
}
ArcNode arc=a.adjlist[start].firstarc;
while(arc!=null)
{if(visited[arc.adjvex]==0)
dfs4(a,arc.adjvex,end,visited,stack,top);
arc=arc.nextarc;
}
if(arc==null) {
top--;visited[start]=0;
//visited[stack[top]]=0;top--;
}
}
public static void dfs5(AGraph a,int start,int end)
{//每次进栈一个元素或出栈一个元素
int visited[]=new int[a.n];//初始化为0
int stack[]=new int[a.n];
int top=-1;
stack[++top]=start;
//stack存放的是adjlist中某一个的位置
visited[start]=1;
while(top!=-1)
{
ArcNode arc=null;
int x=stack[top];
//在if else下面统一出栈,设定为未访问
if(x==end) //栈输出 //9在这里是终点
{ System.out.println("成功");
for(int i=0;i<=top;i++)
System.out.print(stack[i]+" ");
System.out.println("");
}
else
//m是指明arc是x指向的第几个顶点
//这个顶点必须满足:
//①未被访问
//②m必须大于等于ini(小于ini的都已经出栈或不行了,不用考虑)
{arc=a.adjlist[x].firstarc;
int m=1;
while(arc!=null)
{if(visited[arc.adjvex]==0&&m>=a.adjlist[x].ini)
{stack[++top]=arc.adjvex;
visited[arc.adjvex]=1;break;}
else {
arc=arc.nextarc;m++;}}
}
if(arc==null)
//此处逻辑为先出栈,出栈的元素指向的边还原为firstarc
//出栈的元素b一定是出栈后栈顶元素a指向的某一个顶点
//我们找到b是a的第m个顶点,把a的ini设置为m+1
//使其不要重复搜索前m个
//(前面的做法一定是按顺序的,说明前m个已经搜过)
{ int y=stack[top--];//出栈
visited[y]=0;
a.adjlist[y].ini=1;
if(top>=0)
{ ArcNode ar=a.adjlist[stack[top]].firstarc;
int count=1;
//由上面,我们知道进栈的一定>=ini
//所以首先ar要变成ini
while(count<a.adjlist[stack[top]].ini)
{ar=ar.nextarc;
count++;}
//再往下找
int number=ar.adjvex;
while(number!=y)
{a.adjlist[stack[top]].ini++;
ar=ar.nextarc;
number=ar.adjvex;
}
a.adjlist[stack[top]].ini++;
}
}
}
}
public static void dfs6(MGraph m,int start,int end,
int visited[],int stack[],int top)
{ visited[start]=1;
stack[++top]=start;
if(start==end) {
System.out.println("成功");
for(int i=0;i<=top;i++)
System.out.print(stack[i]+" ");
System.out.println("");//出栈
top--;
visited[end]=0;
//visited[stack[top]]=0;top--;
return;
}
for(int i=0;i<m.n;i++)
if(m.edges[start][i]==1&&visited[i]==0)
{
dfs6(m,i,end,visited,stack,top);
}
top--;
visited[start]=0;
}
public static void dfs7(MGraph m,int start,int end)
{//每次进栈一个元素或出栈一个元素
int visited[]=new int[m.n];//初始化为0
int stack[]=new int[m.n];
int top=-1;
stack[++top]=start;
//stack存放的是vex中某一个的位置
visited[start]=1;
while(top!=-1)
{
int x=stack[top];
int ii=m.n;//ii为条件
//在if以及else下面统一出栈
if(x==end) //栈输出
{ System.out.println("成功");
for(int i=0;i<=top;i++)
System.out.print(stack[i]+" ");
System.out.println("");
}
else
//m是指明arc是x指向的第几个顶点
//这个顶点必须满足:
//①未被访问
//②ii必须大于等于x的ini(小于ini的都已经出栈或不行了,不用考虑)
//③ii必须与x有边
{
for(ii=m.vex[x].ini;ii<m.n;ii++)
if(visited[ii]==0&&m.edges[x][ii]!=0)
{stack[++top]=ii;
visited[ii]=1;break;}
}
if(ii==m.n)
//此处逻辑为先出栈,出栈的元素指向的边还原为0
//出栈的元素y一定是出栈后栈顶元素a指向的某一个顶点
//把a的ini设置为y+1
//使其不要重复搜索前y个顶点
//(前面的做法一定是按顺序的,说明前y个已经搜过或者根本不满足条件)
{ int y=stack[top--];//出栈
visited[y]=0;
m.vex[y].ini=0;
if(top>=0)
m.vex[stack[top]].ini=y+1;
}
}
}