/** * 文件名:AdjacencyTable.java * 所在包:Graph * 日期:2014-1-2 上午9:54:32 * 版本信息:version V1.0 * Copyright Corporation 2014 * 版權全部: * */ package Graph; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Scanner; import java.util.Stack; /** * * 項目名稱:jobdu * 類名稱:AdjacencyTable * 類描述:鄰接表: 表結點 + 頭節點 (頂點表 + 邊表) * 建立人:黃傳聰 * 建立時間:2014-1-2 上午9:54:32 * 修改人: * 修改時間: * 修改備註: * @version */ public class AdjacencyTable { /** 鄰接表 (頂點表) */ private List<Vexnode> list; /** 頂點數 */ private int n; /** 邊數 */ private int e; /** 標記是有向圖仍是無向圖 flag=true :無向圖*/ private boolean flag; /** 標識是否訪問 */ private boolean[] visited; public AdjacencyTable(int n, boolean flag) { this.n = n; this.flag = flag; //無向圖 if(flag){ this.e = n * (n - 1 ) / 2; }else{ this.e = n * (n - 1); } visited = new boolean[n]; Arrays.fill(visited, false); } /** * * 項目名稱:jobdu * 類名稱:Arcnode * 類描述:表結點 * 建立人:黃傳聰 * 建立時間:2014-1-2 上午9:55:44 * 修改人: * 修改時間: * 修改備註: * @version */ private final class Arcnode{ private int adjvex; //鄰接點域,指示與幾點vi鄰接的點在圖中的編號 private Arcnode nextarc; // 指示下一條邊或狐的節點 private Object info; //弧的信息 } /** * * 項目名稱:jobdu * 類名稱:Vexnode * 類描述:頭節點域 * 建立人:黃傳聰 * 建立時間:2014-1-2 上午9:58:52 * 修改人: * 修改時間: * 修改備註: * @version */ private final class Vexnode{ //和頂點有關的信息 private int vexData; /** 第一個鄰接點 */ private Arcnode firstArc; } /** * 方法名稱:createAdjacencyTable() * 方法描述:建立鄰接表 * @param flag: 指示建立有向圖仍是無向圖的鄰接表: true 爲 無向圖 * @return String * @throws Exception * @Exception */ public void createAdjacencyTable() throws Exception{ list = new ArrayList<Vexnode>(); Scanner scanner = new Scanner(System.in); Vexnode node = null; //建立頂點表 System.out.println("請輸入頂點值: **************"); for(int i=0;i<n;i++){ node = new Vexnode(); node.vexData = scanner.nextInt(); node.firstArc = null; list.add(node); } System.out.println("請輸入邊: ******************"); //邊表節點 Arcnode arcNode = null; //建立邊表 for(int i=0;i<e;i++){ //輸入一條邊 int begin = scanner.nextInt() ; int end = scanner.nextInt(); if(begin==0 && end==0){ System.out.println(" 建立結束***"); break;//輸入結束 } //若是邊的兩個頂點序號大於列表長短 if(begin > list.size() || end > list.size()){ throw new Exception("begin 或 end 下標越界"); } //以begin爲頭,end爲尾,因爲列表從0開始則都減一 arcNode = new Arcnode(); arcNode.adjvex = end; arcNode.nextarc = null; insertNode(arcNode, begin-1); //建立無向圖 if(flag){ arcNode = new Arcnode(); arcNode.adjvex = begin ; arcNode.nextarc = null; insertNode(arcNode, end-1); } } } /** * 方法名稱:insertNode() * 方法描述 : 插入節點 * @param * @return String * @Exception */ private void insertNode(Arcnode arcNode, int begin) { //查找頂點表,若是頂點爲begin的第一個頂點爲空 if(list.get(begin).firstArc == null){ list.get(begin).firstArc = arcNode; }else{ //若是不爲空,則查找後續列表,找到最後一個頂點插入 Arcnode temp = new Arcnode(); temp = list.get(begin).firstArc; while(temp.nextarc != null){ temp = temp.nextarc; } temp.nextarc = arcNode; } } /** * 方法名稱:dfs() * 方法描述: * @param begin:開始節點 * @return String * @Exception */ public void dfs(int begin){ //正在訪問第 // System.out.println("正在訪問第 " + begin + " 個節點"); System.out.print(list.get(begin).vexData + " -> "); visited[begin] = true;//標識被訪問 Arcnode temp = list.get(begin).firstArc; while(temp != null){ //未被訪問 if(visited[temp.adjvex - 1] == false){ dfs(temp.adjvex - 1);//訪問 } temp = temp.nextarc; } } /** * 方法名稱:dfsRecuive() * 方法描述:深度優先搜索遞歸操做 * @param * @return String * @Exception */ public void dfsRecuive(int begin){ Arrays.fill(visited, false); //設定棧,用於存儲節點序號 Stack<Integer> stack = new Stack<Integer>(); stack.clear(); stack.add(begin); visited[begin] = true; //棧非空 while(!stack.isEmpty()){ //出棧,並訪問 int temp = stack.pop(); System.out.print((temp + 1) + " -> "); //將其未訪問的鄰接點壓入棧 Arcnode node = list.get(temp).firstArc; while(node != null ){ if(visited[node.adjvex - 1] == false){ stack.add(node.adjvex - 1); visited[node.adjvex - 1] = true; } node = node.nextarc; } // visited[begin] = true; } } /** * 方法名稱:bfs() * 方法描述:廣度優先搜索,須要使用隊列輔助 * @param * @return String * @Exception */ public void bfs(int begin){ Arrays.fill(visited, false); Queue<Integer> queue = new LinkedList<Integer>(); System.out.print((begin + 1) + " -> "); visited[begin] = true; queue.clear(); //將頂點序號加入到隊列中 queue.add(begin); //隊列非空 while(!queue.isEmpty()){ //隊頭元素出隊列 int temp = queue.poll(); //獲取隊頭元素的第一個鄰接點 Arcnode node = list.get(temp).firstArc; while(node != null){ //節點未被訪問 if(visited[node.adjvex - 1] == false){ //開始訪問 System.out.print(node.adjvex + " -> "); visited[node.adjvex - 1] = true; //節點的頂點信息入棧 queue.add(node.adjvex - 1); } node = node.nextarc; } } } /** * 方法名稱:search() * 方法描述:查找聯通份量或強連通圖 * @param * @return String * @Exception */ public void searchConnectedComponent(){ //標識是不是連通圖,默認是 System.out.println(" ***查找連通圖開始******"); boolean flag = true; for(int i=0;i<n;i++){ //若是頂點沒有被遍歷,以該節點爲入口查詢 if(visited[i] == false){ flag = false; System.out.println(" *******查詢連通份量 入口節點爲: " + (i+1) + "**********"); dfs(i); //bfs(i); System.out.println(); System.out.println(" ********以 " + (i+1) + " 爲入口的聯通份量查詢結束 ********"); } } if(flag){ System.out.println(" 其爲連通圖,連通份量爲其自己!"); } System.out.println(" ***查找連通圖結束******"); } public static void main(String[] args) throws Exception{ AdjacencyTable table = new AdjacencyTable(8 , true); table.createAdjacencyTable(); /*System.out.println("The first adjvex is : " + table.list.get(0).firstArc.adjvex); System.out.println("深度度優先搜索遞歸方式: **************"); table.dfs(0); System.out.println(); System.out.println("深度度優先搜索非遞歸方式: **************"); table.dfsRecuive(0); System.out.println(); System.out.println("廣度優先搜索: **************");*/ /* for(boolean b : table.visited){ System.out.println(b); } */ // table.bfs(0); // System.out.println(); table.searchConnectedComponent(); } public List<Vexnode> getList() { return list; } public void setList(List<Vexnode> list) { this.list = list; } public int getN() { return n; } public void setN(int n) { this.n = n; } public int getE() { return e; } public void setE(int e) { this.e = e; } }