java計(jì)算圖兩點(diǎn)之間的所有路徑
本文實(shí)例為大家分享了java計(jì)算圖兩點(diǎn)之間的所有路徑的具體代碼,供大家參考,具體內(nèi)容如下
1.給定圖如下:

2.求0到3之間可達(dá)的所有路徑
這里問(wèn)題就是關(guān)于搜索遍歷的問(wèn)題,但其中需要注意到不能產(chǎn)生回路或環(huán).
算法描述如下:
top_node:當(dāng)前棧頂元素
adjvex_node;當(dāng)前top_node已經(jīng)訪問(wèn)的鄰接點(diǎn)
next_node:即將訪問(wèn)的元素(top_node的第adjvex_node個(gè)鄰接點(diǎn)所對(duì)應(yīng)的元素)
找出所有路徑采用的是遍歷的方法,以“深度優(yōu)先”算法為基礎(chǔ)。從源點(diǎn)出發(fā),先到源點(diǎn)的第一個(gè)鄰接點(diǎn)N00,再到N00的第一個(gè)鄰接點(diǎn)N10,再到N10的第一個(gè)鄰接點(diǎn)N20...當(dāng)遍歷到目標(biāo)點(diǎn)時(shí)表明找到一條路徑。
上述代碼的核心數(shù)據(jù)結(jié)構(gòu)為一個(gè)棧,主要步驟:
①源點(diǎn)先入棧,并進(jìn)行標(biāo)記
②獲取棧頂元素top_node,如果棧頂為終點(diǎn)時(shí),即找到一條路徑,棧頂元素top_node出棧,此時(shí)adjvex_node=top_node,新的棧頂元素為top_node,否則執(zhí)行③
③從top_node的所有鄰接點(diǎn)中,從adjvex_node為起點(diǎn),選取下一個(gè)鄰接點(diǎn)next_node;如果該元素非空,則入棧,使得adjvex_node=-1,(adjvex_node=-1代表top_node的鄰接點(diǎn)一個(gè)還沒(méi)有訪問(wèn))做入棧標(biāo)記。否則代表沒(méi)有后續(xù)節(jié)點(diǎn)了,此時(shí)必須出棧棧頂元素,并置adjvex_node為該棧頂元素,并做出棧標(biāo)記。
④為避免回路,已入棧元素要記錄,選取新入棧頂點(diǎn)時(shí)應(yīng)跳過(guò)已入棧的頂點(diǎn),當(dāng)棧為空時(shí),遍歷完成
3.java代碼實(shí)現(xiàn)
1)圖結(jié)構(gòu)
點(diǎn)表
public class Vertex {
//存放點(diǎn)信息
public int data;
//與該點(diǎn)鄰接的第一個(gè)邊節(jié)點(diǎn)
public Edge firstEdge;
}
邊表(代表與點(diǎn)相連的點(diǎn)的集合)
//邊節(jié)點(diǎn)
public class Edge {
//對(duì)應(yīng)的點(diǎn)下表
public int vertexId;
//邊的權(quán)重
public int weight;
//下一個(gè)邊節(jié)點(diǎn)
public Edge next;
//getter and setter自行補(bǔ)充
}
2).算法實(shí)現(xiàn)
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
public class graph {
public Vertex[] vertexList; //存放點(diǎn)的集合
public graph(int vertexNum){
this.vertexNum=vertexNum;
vertexList=new Vertex[vertexNum];
}
//點(diǎn)個(gè)數(shù)
public int vertexNum;
//邊個(gè)數(shù)
public int edgeLength;
public void initVertext(int datas[]){
for(int i=0;i<vertexNum;i++){
Vertex vertext=new Vertex();
vertext.data=datas[i];
vertext.firstEdge=null;
vertexList[i]=vertext;
//System.out.println("i"+vertexList[i]);
}
isVisited=new boolean[vertexNum];
for(int i=0;i<isVisited.length;i++){
isVisited[i]=false;
}
}
//針對(duì)x節(jié)點(diǎn)添加邊節(jié)點(diǎn)y
public void addEdge(int x,int y,int weight){
Edge edge=new Edge();
edge.setVertexId(y);
edge.setWeight(weight);
//第一個(gè)邊節(jié)點(diǎn)
System.out.println(vertexList.length);
if(null==vertexList[x].firstEdge){
vertexList[x].firstEdge=edge;
edge.setNext(null);
}
//不是第一個(gè)邊節(jié)點(diǎn),則采用頭插法
else{
edge.next=vertexList[x].firstEdge;
vertexList[x].firstEdge=edge;
}
}
//得到x的鄰接點(diǎn)為y的后一個(gè)鄰接點(diǎn)位置,為-1說(shuō)明沒(méi)有找到
public int getNextNode(int x,int y){
int next_node=-1;
Edge edge=vertexList[x].firstEdge;
if(null!=edge&&y==-1){
int n=edge.vertexId;
//元素還不在stack中
if(!states.get(n))
return n;
return -1;
}
while(null!=edge){
//節(jié)點(diǎn)未訪問(wèn)
if(edge.vertexId==y){
if(null!=edge.next){
next_node=edge.next.vertexId;
if(!states.get(next_node))
return next_node;
}
else
return -1;
}
edge=edge.next;
}
return -1;
}
//代表某節(jié)點(diǎn)是否在stack中,避免產(chǎn)生回路
public Map<Integer,Boolean> states=new HashMap();
//存放放入stack中的節(jié)點(diǎn)
public Stack<Integer> stack=new Stack();
//輸出2個(gè)節(jié)點(diǎn)之間的輸出路徑
public void visit(int x,int y){
//初始化所有節(jié)點(diǎn)在stack中的情況
for(int i=0;i<vertexNum;i++){
states.put(i,false);
}
//stack top元素
int top_node;
//存放當(dāng)前top元素已經(jīng)訪問(wèn)過(guò)的鄰接點(diǎn),若不存在則置-1,此時(shí)代表訪問(wèn)該top元素的第一個(gè)鄰接點(diǎn)
int adjvex_node=-1;
int next_node;
stack.add(x);
states.put(x,true);
while(!stack.isEmpty()){
top_node=stack.peek();
//找到需要訪問(wèn)的節(jié)點(diǎn)
if(top_node==y){
//打印該路徑
printPath();
adjvex_node=stack.pop();
states.put(adjvex_node,false);
}
else{
//訪問(wèn)top_node的第advex_node個(gè)鄰接點(diǎn)
next_node=getNextNode(top_node,adjvex_node);
if(next_node!=-1){
stack.push(next_node);
//置當(dāng)前節(jié)點(diǎn)訪問(wèn)狀態(tài)為已在stack中
states.put(next_node,true);
//臨接點(diǎn)重置
adjvex_node=-1;
}
//不存在臨接點(diǎn),將stack top元素退出
else{
//當(dāng)前已經(jīng)訪問(wèn)過(guò)了top_node的第adjvex_node鄰接點(diǎn)
adjvex_node=stack.pop();
//不在stack中
states.put(adjvex_node,false);
}
}
}
}
//打印stack中信息,即路徑信息
public void printPath(){
StringBuilder sb=new StringBuilder();
for(Integer i :stack){
sb.append(i+"->");
}
sb.delete(sb.length()-2,sb.length());
System.out.println(sb.toString());
}
public static void main(String[]args){
graph g=new graph(5);
g.initVertext(new int[]{1,2,3,4,4});
//System.out.println(g.vertexList[0]);
g.addEdge(0,1,1);
g.addEdge(0,2,3);
g.addEdge(0,3,4);
g.addEdge(1,2,1);
g.addEdge(2,0,1);
g.addEdge(2,3,1);
g.addEdge(1,3,2);
g.visit(0,3);
}
}
執(zhí)行結(jié)果如下:
0->3
0->2->3
0->1->2->3
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot + JPA @ManyToMany的操作要點(diǎn)說(shuō)明
這篇文章主要介紹了SpringBoot + JPA @ManyToMany的操作要點(diǎn)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
SpringBoot項(xiàng)目中配置application.yml中server.port不生效的問(wèn)題
這篇文章主要介紹了SpringBoot項(xiàng)目中配置application.yml中server.port不生效的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
十大常見(jiàn)Java String問(wèn)題_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
本文介紹Java中關(guān)于String最常見(jiàn)的10個(gè)問(wèn)題,需要的朋友參考下吧2017-04-04
java方法重寫(重點(diǎn)講),方法重載問(wèn)題
這篇文章主要介紹了java方法重寫(重點(diǎn)講),方法重載問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
Jenkins初級(jí)應(yīng)用之Invoke?Phing?targets插件配置
這篇文章主要為大家介紹了Jenkins初級(jí)應(yīng)用之Invoke?Phing?targets的插件配置,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪<BR>2022-04-04
Java設(shè)計(jì)模式七大原則之開(kāi)閉原則詳解
開(kāi)閉原則,又稱為OCP原則,即一個(gè)軟件實(shí)體如類,模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。本文將詳細(xì)介紹Java設(shè)計(jì)模式七大原則之一的開(kāi)閉原則,需要的可以參考一下2022-02-02
java基礎(chǔ)理論Stream的Filter與謂詞邏輯
這篇文章主要為大家介紹了java基礎(chǔ)理論Stream的Filter與謂詞邏輯,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03
SpringCloud網(wǎng)關(guān)(Zuul)如何給多個(gè)微服務(wù)之間傳遞共享參數(shù)
這篇文章主要介紹了SpringCloud網(wǎng)關(guān)(Zuul)如何給多個(gè)微服務(wù)之間傳遞共享參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Java中的ReadWriteLock高效處理并發(fā)讀寫操作實(shí)例探究
這篇文章主要為大家介紹了Java中的ReadWriteLock高效處理并發(fā)讀寫操作實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01

