Java實現演算法導論中圖的廣度優先搜尋(BFS)和深度優先搜尋(DFS)
阿新 • • 發佈:2019-01-09
對演算法導論中圖的廣度優先搜尋(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
演算法還是有改良空間,比如怎麼控制生成樹是最大子樹。