圖+鄰接表+圖的遍歷

/**
 * 文件名: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;
	}
	
	
}
相關文章
相關標籤/搜索