1. 程式人生 > >深度優先dfs求解兩點間所有路徑

深度優先dfs求解兩點間所有路徑

鄰接表:
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;
		   
		}
      }
	}