1. 程式人生 > >Java實現演算法導論中圖的廣度優先搜尋(BFS)和深度優先搜尋(DFS)

Java實現演算法導論中圖的廣度優先搜尋(BFS)和深度優先搜尋(DFS)

對演算法導論中圖的廣度優先搜尋(BFS)和深度優先搜尋(DFS)用Java實現其中的虛擬碼演算法,案例也採用演算法導論中的圖。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;

public class GraphSearch {
	
	final static HashMap<String,LinkedList<String>> DGraph=new HashMap<String,LinkedList<String>>(); //有向圖
	final static HashMap<String,LinkedList<String>> UGraph=new HashMap<String,LinkedList<String>>(); //無向圖
	public static final int MAX_VALUE=2147483647;
	public static final int MIN_VALUE=-2147483648;
	public static void main(String [] args) {   
		//鄰接表表示,初始化有向圖和無向圖,圖用演算法導論中的案例,分別是圖22-1和圖22-2
		GraphSearch.initUGraph();
		GraphSearch.initDGraph();		
		//BFS廣度優先搜尋
		//GraphSearch.BFSUGraph();
		//GraphSearch.BFSDGraph();
		//DFS深度優先搜尋
		GraphSearch gs=new GraphSearch();
		//gs.DFSUGraph();
		gs.DFSDGraph();
	}
	//深度優先搜尋
	//初始化六個頂點的顏色、父頂點、發現距離和結束距離
	public  String[] DDColor = new String[]{"white","white","white","white","white","white"};
	public  int[] DDDis=new int[]{MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE};
	public  int[] DDFin=new int[]{MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE};
	public  String[] DDParent=new String[]{"null","null","null","null","null","null"};
	public  int DDTime=0;//計算髮現時間和結束時間
	public void DFSDGraph(){//有向圖深度優先搜尋
		//遍歷鄰接表
		Iterator<Entry<String, LinkedList<String>>> iter=DGraph.entrySet().iterator();	
		while (iter.hasNext() ) {
			Map.Entry<String, LinkedList<String>> entry = iter.next();
			String key = entry.getKey();
			int iKey=Integer.valueOf(key.substring(1))-1;
			if (DDColor[iKey]=="white") DFSDGraphVisit(key);
		}
	}
	public void DFSDGraphVisit(String key){//無向圖深度優先搜尋
		int n=Integer.valueOf(key.substring(1))-1;
		DDColor[n]="gray";
		DDTime=DDTime+1;
		DDDis[n]=DDTime;
		LinkedList<String> llV=DGraph.get(key);
		for(int i=0;i<llV.size();i++){
			String strV=llV.get(i);
			int m=Integer.valueOf(strV.substring(1))-1;
			if(DDColor[m]=="white"){
				DDParent[m]=key;
				DFSDGraphVisit(strV);
			}
		}	
		DDColor[n]="black";
		DDTime=DDTime+1;
		DDFin[n]=DDTime;
		System.out.println("頂點:"+key+"發現時間:"+String.valueOf(DDDis[n])+"結束時間:"+String.valueOf(DDFin[n])+"父頂點:"+DDParent[n]+"當前顏色:"+DDColor[n]);
	}

	//初始化五個頂點的顏色、父頂點、發現距離和結束距離
	public  String[] DUColor = new String[]{"white","white","white","white","white"};
	public  int[] DUDis=new int[]{MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE};
	public  int[] DUFin=new int[]{MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE};
	public  String[] DUParent=new String[]{"null","null","null","null","null"};
	public  int DUTime=0;//計算髮現時間和結束時間
	public  void DFSUGraph(){//無向圖深度優先搜尋	
		//遍歷鄰接表
		Iterator<Entry<String, LinkedList<String>>> iter=UGraph.entrySet().iterator();	
		while (iter.hasNext() ) {
		    Map.Entry<String, LinkedList<String>> entry = iter.next();
		    String key = entry.getKey();
		    int iKey=Integer.valueOf(key.substring(1))-1;
		    if (DUColor[iKey]=="white") DFSUGraphVisit(key);
		}
	}
	public void DFSUGraphVisit(String key){//無向圖深度優先搜尋
		int n=Integer.valueOf(key.substring(1))-1;
		DUColor[n]="gray";
		DUTime=DUTime+1;
		DUDis[n]=DUTime;
		LinkedList<String> llV=UGraph.get(key);
		for(int i=0;i<llV.size();i++){
			String strV=llV.get(i);
			int m=Integer.valueOf(strV.substring(1))-1;
			if(DUColor[m]=="white"){
				DUParent[m]=key;
				DFSUGraphVisit(strV);
			}
		}	
		DUColor[n]="black";
		DUTime=DUTime+1;
		DUFin[n]=DUTime;
		System.out.println("頂點:"+key+"發現時間:"+String.valueOf(DUDis[n])+"結束時間:"+String.valueOf(DUFin[n])+"父頂點:"+DUParent[n]+"當前顏色:"+DUColor[n]);
	}
	
	//廣度優先搜尋
	public static void BFSDGraph(){//有向圖廣度優先搜尋
		//有向圖DFS演算法要改良,多個源頂點生成多顆樹
		//選初始化六個的顏色、父頂點、最短距離
		String[] color = new String[]{"white","white","white","white","white","white"};
		int[] dist=new int[]{MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE};
		String[] parent=new String[]{"null","null","null","null","null","null"};
		//遍歷頂點表DGraph,看是否還存在未搜尋的
		ArrayList<String> ALV=new ArrayList<String> ();
		Iterator<Entry<String, LinkedList<String>>> iter=DGraph.entrySet().iterator();	
		while (iter.hasNext() && ALV.size()<6) {
		    Map.Entry<String, LinkedList<String>> entry = iter.next();
			String key = entry.getKey();
			if(ALV.contains(key)) continue;//已搜尋,下次迴圈
			//LinkedList<String> val = entry.getValue();
			int iSV=Integer.valueOf(key.substring(1))-1;
			//初始化源頂點
			color[iSV]="gray";
			dist[iSV]=0;
			parent[iSV]="null";
			ArrayList<String> queue=new ArrayList<String>();
			queue.add(key);
			//開始搜尋
			while(queue.size()>0){
				String strV=queue.get(0);
				queue.remove(0);//出列
				int m=Integer.valueOf(strV.substring(1))-1;
				LinkedList<String> listV= DGraph.get(strV);
				for(int i=0;i<listV.size();i++){
					String strVTmp=listV.get(i);
					int n=Integer.valueOf(strVTmp.substring(1))-1;//頂點名稱第二個字元是數字
					if(color[n]=="white"){
						color[n]="gray";
						dist[n]=dist[m]+1;
						parent[n]=strV;
						queue.add(strVTmp);
						}
					}
				color[m]="black";
				System.out.println("頂點:"+strV+"最短距離:"+String.valueOf(dist[m])+"父頂點:"+parent[m]+"當前顏色:"+color[m]);
				ALV.add(strV);
			}		
		}
	}
	public static void BFSUGraph(){//無向圖廣度優先搜尋
		//選擇頂點V1為源點,初始化五個的顏色、父頂點、最短距離
		String[] color = new String[]{"white","white","white","white","white"};
		int[] dist=new int[]{MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE,MAX_VALUE};
		String[] parent=new String[]{"null","null","null","null","null"};
		//初始化源頂點V1
		color[0]="gray";
		dist[0]=0;
		parent[0]="null";
		ArrayList<String> queue=new ArrayList<String>();
		queue.add("V1");
		//開始搜尋
		while(queue.size()>0){
			String strV=queue.get(0);
			queue.remove(0);//出列
			int m=Integer.valueOf(strV.substring(1))-1;
			LinkedList<String> listV= UGraph.get(strV);
			for(int i=0;i<listV.size();i++){
				String strVTmp=listV.get(i);
				int n=Integer.valueOf(strVTmp.substring(1))-1;//頂點名稱第二個字元是數字
				if(color[n]=="white"){
					color[n]="gray";
					dist[n]=dist[m]+1;
					parent[n]=strV;
					queue.add(strVTmp);
				}
			}
			color[m]="black";
			System.out.println("頂點:"+strV+"最短距離:"+String.valueOf(dist[m])+"父頂點:"+parent[m]+"當前顏色:"+color[m]);
		}		
	}
	//初始化圖	
	public static void initUGraph(){//無向圖初始化
		//頂點V1的鄰接表
		String strV1="V1";
		LinkedList<String> ListV1=new LinkedList<String>();
		ListV1.add("V2");
		ListV1.add("V5");
		UGraph.put(strV1, ListV1);
		//頂點V2的鄰接表
		String strV2="V2";
		LinkedList<String> ListV2=new LinkedList<String>();
		ListV2.add("V1");
		ListV2.add("V5");
		ListV2.add("V3");
		ListV2.add("V4");
		UGraph.put(strV2, ListV2);
		//頂點V3的鄰接表
		String strV3="V3";
		LinkedList<String> ListV3=new LinkedList<String>();
		ListV3.add("V2");
		ListV3.add("V4");
		UGraph.put(strV3, ListV3);
		//頂點V4的鄰接表
		String strV4="V4";
		LinkedList<String> ListV4=new LinkedList<String>();
		ListV4.add("V2");
		ListV4.add("V5");
		ListV4.add("V3");
		UGraph.put(strV4, ListV4);
		//頂點V5的鄰接表
		String strV5="V5";
		LinkedList<String> ListV5=new LinkedList<String>();
		ListV5.add("V4");
		ListV5.add("V1");
		ListV5.add("V2");
		UGraph.put(strV5, ListV5);
	}
	public static void initDGraph(){//有向圖初始化
		//頂點V1的鄰接表
		String strV1="V1";
		LinkedList<String> ListV1=new LinkedList<String>();
		ListV1.add("V2");
		ListV1.add("V4");
		DGraph.put(strV1, ListV1);
		//頂點V2的鄰接表
		String strV2="V2";
		LinkedList<String> ListV2=new LinkedList<String>();
		ListV2.add("V5");
		DGraph.put(strV2, ListV2);
		//頂點V3的鄰接表
		String strV3="V3";
		LinkedList<String> ListV3=new LinkedList<String>();
		ListV3.add("V6");
		ListV3.add("V5");
		DGraph.put(strV3, ListV3);
		//頂點V4的鄰接表
		String strV4="V4";
		LinkedList<String> ListV4=new LinkedList<String>();
		ListV4.add("V2");
		DGraph.put(strV4, ListV4);
		//頂點V5的鄰接表
		String strV5="V5";
		LinkedList<String> ListV5=new LinkedList<String>();
		ListV5.add("V4");
		DGraph.put(strV5, ListV5);
		//頂點V6的鄰接表
		String strV6="V6";
		LinkedList<String> ListV6=new LinkedList<String>();
		ListV6.add("V6");
		DGraph.put(strV6, ListV6);
		
		
		/*List arrayList = new ArrayList(DGraph.entrySet());
		Collections.sort(arrayList, new Comparator() {  
			public int compare(Object arg1, Object arg2) {  
				Map.Entry obj1 = (Map.Entry) arg1; 
				Map.Entry obj2 = (Map.Entry) arg2;  
				return (obj1.getKey()).toString().compareTo((String) obj2.getKey());  
		  }  
		}); 
		//將HASHMAP中的資料排序  
		for (Iterator iter = arrayList.iterator(); iter.hasNext();)  {  
		   Map.Entry entry = (Map.Entry)iter.next();  
		   String  key = (String)entry.getKey();  
		   System.out.println(key);    
		}*/
		/*Iterator<Entry<String, LinkedList<String>>> iter=DGraph.entrySet().iterator();	
		while (iter.hasNext() ) {
		    Map.Entry<String, LinkedList<String>> entry = iter.next();
			System.out.println(entry.getKey());
		}*/
	}
	
	
}
結果:

1)無向圖廣度優先搜尋:

頂點:V1最短距離:0父頂點:null當前顏色:black
頂點:V2最短距離:1父頂點:V1當前顏色:black
頂點:V5最短距離:1父頂點:V1當前顏色:black
頂點:V3最短距離:2父頂點:V2當前顏色:black
頂點:V4最短距離:2父頂點:V2當前顏色:black

2)有向圖廣度優先搜尋
頂點:V2最短距離:0父頂點:null當前顏色:black
頂點:V5最短距離:1父頂點:V2當前顏色:black
頂點:V4最短距離:2父頂點:V5當前顏色:black
頂點:V3最短距離:0父頂點:null當前顏色:black
頂點:V6最短距離:1父頂點:V3當前顏色:black
頂點:V1最短距離:0父頂點:null當前顏色:black

3)無向圖深度優先搜尋
頂點:V3發現時間:5結束時間:6父頂點:V4當前顏色:black
頂點:V4發現時間:4結束時間:7父頂點:V5當前顏色:black
頂點:V5發現時間:3結束時間:8父頂點:V1當前顏色:black
頂點:V1發現時間:2結束時間:9父頂點:V2當前顏色:black
頂點:V2發現時間:1結束時間:10父頂點:null當前顏色:black


4)有向圖深度優先搜尋

頂點:V4發現時間:3結束時間:4父頂點:V5當前顏色:black
頂點:V5發現時間:2結束時間:5父頂點:V2當前顏色:black
頂點:V2發現時間:1結束時間:6父頂點:null當前顏色:black
頂點:V6發現時間:8結束時間:9父頂點:V3當前顏色:black
頂點:V3發現時間:7結束時間:10父頂點:null當前顏色:black
頂點:V1發現時間:11結束時間:12父頂點:null當前顏色:black

演算法還是有改良空間,比如怎麼控制生成樹是最大子樹。