DFS與BFS較爲簡單,是圖論的基礎。在以後的實驗中,不管是動態規劃、貪心算法、回溯法都會以DFS或BFS爲基礎,應當是我們每個人都要掌握的。
在這裏分享一個關於DFS的JAVA實現算法。
深度優先搜索的算法描述如下:
從圖中某頂點v出發:
(1)訪問頂點v;
(2)依次從v的未被訪問的鄰接點出發,對圖進行深度優先遍歷;直至圖中和v有路徑相通的頂點都被訪問;
(3)若此時圖中尚有頂點未被訪問,則從一個未被訪問的頂點出發,重新進行深度優先遍歷,直到圖中所有頂點均被訪問過爲止。具體設計:
1. 數據結構
採用鄰接鏈表作爲圖的數據結構。而我是用的鄰接鏈表法分爲三個類,即圖類Graph,頭節點類VNode,邊類ArcNode。由於這段數據結構涉及到之後會提到的圖類算法,部分屬性在單純的DFS中是不必要的,大家可以根據自己的需求對各個類進行修改。
其具體設計如下:
public class Graph {//圖
public VNode[] arrVnode=new VNode[100] ;//頭結點數組
public int vexmun,arcmun;//節點總數、邊界總數
public int time;//記錄打開、關閉節點的時間
}
public class VNode {//頭節點類
public int data;//節點的內容
public boolean visited=false;//是否訪問過
public boolean ifclosed=false;//是否被放在關閉的表中
public int distance=10000;//距離某一點的最短距離
public int front=10000;//前驅節點
public ArcNode nextarc=null;//下一條邊
public int entertime,exittime;//打開、關閉節點的時間
}
public class ArcNode{//邊類
public int adjvex;//該弧所指向的頂點的位置
public int weight=0;//該邊的權值
public ArcNode nextarc=null;//下一條邊
}
2.圖的初始化
package Graph;
import Queue.*;
//import javax.swing.*;
public class GrahpFunction {
Graph Graph1=new Graph();
public Graph CreateGrahp(int vexnum,int arcnum,int[] a,int[] b,int[] c){
Graph1.vexmun=vexnum;
Graph1.arcmun=arcnum;
for(int i=1;i<=Graph1.vexmun;i++){
VNode d= new VNode();
Graph1.arrVnode[i]=d;
Graph1.arrVnode[i].data=i;
Graph1.arrVnode[i].nextarc=null;
}
for(int arc=1;arc<=Graph1.arcmun;arc++){
int startint=a[arc];//開始節點
int endint=b[arc];//結束節點
int weightint=c[arc];//權值
// int weightint=return_position(Integer.parseInt(Weight));
if(Graph1.arrVnode[startint].nextarc==null){
ArcNode ArcNode_p=new ArcNode();//這是一個邊
ArcNode_p.adjvex=endint;
ArcNode_p.nextarc=null;
ArcNode_p.weight=weightint;
Graph1.arrVnode[startint].nextarc=ArcNode_p;
}else{
ArcNode p=Graph1.arrVnode[startint].nextarc;
while(p.nextarc!=null){
p=p.nextarc;
}
ArcNode ArcNode_p=new ArcNode();
ArcNode_p.adjvex=endint;
ArcNode_p.nextarc=null;
ArcNode_p.weight=weightint;
p.nextarc=ArcNode_p;
}
}
for(int i=1;i<=Graph1.vexmun;i++){
visited[i]=false;
queueed[i]=false;
}
return Graph1;
}
public int return_position(int data){
for(int j=1;j<=Graph1.vexmun;j++){
if(data==Graph1.arrVnode[j].data){
return j;
}
}
return 0;
}
boolean[] visited=new boolean[100];
boolean[] queueed=new boolean[100];
}
3.DFS算法
這個算法由兩部分組成,遍歷所有節點的DFS(GraphG),與遞歸調用的DFS_VISIT(G,v)。
在使用的過程中,需要對DFS類進行初始化,從DFS方法開始調用,遍歷所有節點防止有節點沒有訪問到。
public void DFS(Graph G){//DFS的起始調用方法
int vexmun=G.vexmun;
G.time=0;
for(int v=1;v<=vexmun;v++){
if(G.arrVnode[v].visited==false){
DFS_VISIT(G,v);
}
}
}
public void DFS_VISIT(Graph G,int v){//應用遞歸的DFS訪問
G.arrVnode[v].visited=true;
G.time++;//time是給後面的拓撲排序實驗用的
G.arrVnode[v].entertime=G.time;
System.out.println(G.arrVnode[v].data);
ArcNode node=G.arrVnode[v].nextarc;
while(node!=null){
int p=node.adjvex;
if(G.arrVnode[p].visited==false&&G.arrVnode[p]!=null){
DFS_VISIT( G , p);
}
node=node.nextarc;
}
G.time++;
G.arrVnode[v].exittime=G.time;
}
4.主函數
主函數測試的時候,我採用的是文件輸入的方式,用了普林斯頓大學《算法(第四版)》提供的外部函數庫stdlib.jar,而且之後的一些涉及到排序的算法我也是用了其提供的algs4.jar,有需要的同學可以去網上下載一下。
public class Test_DFS {
public static void main(String[] args){
int[] a=new int[10000];
int[] b=new int[10000];
int[] c=new int[10000];
int[] shortest=new int[10000];////////////////
In in = new In(args[0]);
int vexnum=in.readInt();
int arcnum=in.readInt();
for(int arc=1;arc<=arcnum;arc++){
a[arc]=in.readInt();
b[arc]=in.readInt();
c[arc]=in.readInt();
}
for(int arc=1;arc<=arcnum;arc++){
shortest[arc]=10000;
}
GrahpFunction GrahpFuntion=new GrahpFunction();
Queue Queue=new Queue();
Graph G=GrahpFuntion.CreateGrahp(vexnum,arcnum,a,b,c);
Toposort top=new Toposort();
top.Toposortmethod(G);
System.out.println("DFS結果爲:");
GrahpFuntion.DFS1(G);