package graphi;
import java.util.LinkedList;
import java.util.Queue;
/**
* 採用鄰接表的方式存儲無向圖
*/
public class UnGraphi {
//標識圖中的頂點個數
private int points;
//鄰接表
private LinkedList<Integer> [] adjacencyList;
public UnGraphi(int points){
this.points = points;
adjacencyList = new LinkedList[this.points];
//初始化數組中每一個槽位上鍊表
for(int i=0;i<this.points;i++){
adjacencyList[i] = new LinkedList<Integer>();
}
}
/**
* 向圖中添加頂點(邊)
*/
public void addPoint(int s,int t){
adjacencyList[s].add(t);
adjacencyList[t].add(s);
}
/**
* 廣度優先搜索算法實現
* @param s 起始頂點
* @param t 目標頂點
*/
public void bfs(int s,int t){
if(s==t){
//起始頂點就是目標頂點
return;
}
//定義一個boolean數組,用來記錄頂點是否被訪問
boolean[] visited = new boolean[this.points];
//起始頂點已經被訪問
visited[s] = true;
//定義一個隊列,存儲已經被訪問的,但是還有相鄰頂點的頂點
Queue<Integer> queue = new LinkedList<Integer>();
queue.add(s);
//定義一個數組來存儲我們的s-t線路
int[] prev = new int[this.points];
//初始化爲線路爲1
for(int i=0;i<prev.length;i++){
prev[i] = -1;
}
//循環訪問對列中沒有被訪問的頂點
while (!queue.isEmpty()) {
//取出訪問過的但是有相鄰頂點的頂點
Integer p = queue.poll();
//遍歷這個頂點的相鄰頂點
for (int j=0;j<adjacencyList[p].size();j++){
//取出相鄰頂點
Integer p_edge = adjacencyList[p].get(j);
//相鄰頂點沒有被訪問過
if(!visited[p_edge]){
//記錄訪問路線
prev[p_edge] = p;
//如果該頂點與目標頂點相等,就打印訪問路線
if(p_edge == t){
print(prev,s,t);
return;
}
//否則標記P爲已經訪問過的頂點
visited[p] = true;
//相鄰頂點存入隊列
queue.add(p_edge);
}
}
}
}
/**
* 打印從s-t線路的方法
*/
public void print(int[] prev,int s,int t){
if(prev[t] != -1 && s!=t){
print(prev,s,prev[t]);
}
System.out.print(t+">>");
}
//標記我們是否找到目標頂點
private boolean found = false;
/**
* 深度優先搜索算法
* @param s
* @param t
*/
public void dfs(int s,int t){
if(s==t){
return;
}
//標記元素是否被訪問過
boolean [] visited = new boolean[this.points];
visited[s] = true;
//定義一個數組記錄我們從原頂點到目標頂點之間的線路
int [] prv = new int[this.points];
for (int i=0;i<prv.length;i++){
prv[i]=-1;
}
//遞歸調用
returnDFS(s,t,visited,prv);
//打印線路
print(prv,s,t);
}
/**
* 查找頂點point到目標頂點的線路
* @param point 頂點
* @param target 目標頂點
* @param visited 已經被訪問過的頂點數組
* @param prev 頂點線路數組
*/
private void returnDFS(int point,int target,boolean [] visited,int [] prev){
if(found){
return;
}
//標記當前頂點已經被訪問
visited[point] = true;
//如果當前頂點就是目標頂點
if(point == target){
found = true;
return;
}
//獲取與當前頂點相連接的所有頂點
for(int j=0;j<adjacencyList[point].size();j++){
//獲取與頂點pouint相連的頂點
Integer p_conect = adjacencyList[point].get(j);
if(!visited[p_conect]){
//記錄p_connect之前的頂點是P
prev[p_conect] = point;
//遞歸
returnDFS(p_conect,target,visited,prev);
}
}
}
public static void main(String[] args) {
UnGraphi unGraphi = new UnGraphi(8);
unGraphi.addPoint(0,1);
unGraphi.addPoint(0,3);
unGraphi.addPoint(1,2);
unGraphi.addPoint(1,4);
unGraphi.addPoint(2,5);
unGraphi.addPoint(3,4);
unGraphi.addPoint(4,5);
unGraphi.addPoint(4,6);
unGraphi.addPoint(6,7);
unGraphi.addPoint(7,5);
// System.out.println(unGraphi);
//unGraphi.bfs(0,6);
unGraphi.dfs(0,6);
}
}