java查找無向連通圖中兩點間所有路徑的算法
之前就這個問題發(fā)帖求教過,過了幾天沒看到回復就沒再關(guān)心。后來自己設(shè)計了一個算法,在公司的項目中實踐了一下,效果還可以,貼出來供大家參考。
算法要求:
1. 在一個無向連通圖中求出兩個給定點之間的所有路徑;
2. 在所得路徑上不能含有環(huán)路或重復的點;
算法思想描述:
1. 整理節(jié)點間的關(guān)系,為每個節(jié)點建立一個集合,該集合中保存所有與該節(jié)點直接相連的節(jié)點(不包括該節(jié)點自身);
2. 定義兩點一個為起始節(jié)點,另一個為終點,求解兩者之間的所有路徑的問題可以被分解為如下所述的子問題:對每一個與起始節(jié)點直接相連的節(jié)點,求解它到終點的所有路徑(路徑上不包括起始節(jié)點)得到一個路徑集合,將這些路徑集合相加就可以得到起始節(jié)點到終點的所有路徑;依次類推就可以應用遞歸的思想,層層遞歸直到終點,若發(fā)現(xiàn)希望得到的一條路徑,則轉(zhuǎn)儲并打印輸出;若發(fā)現(xiàn)環(huán)路,或發(fā)現(xiàn)死路,則停止尋路并返回;
3. 用棧保存當前已經(jīng)尋到的路徑(不是完整路徑)上的節(jié)點,在每一次尋到完整路徑時彈出棧頂節(jié)點;而在遇到從棧頂節(jié)點無法繼續(xù)向下尋路時也彈出該棧頂節(jié)點,從而實現(xiàn)回溯。
算法偽碼(java描述):
public Stack stack = new Stack();/*臨時保存路徑節(jié)點的棧*/ public ArrayList sers = new ArrayList();/*存儲路徑的集合*/ public class Node/*表示一個節(jié)點以及和這個節(jié)點相連的所有節(jié)點*/ { public String name = null; public ArrayList relationNodes = new ArrayList(); public String getName() { return name; } public void setName(String name) { this.name = name; } public ArrayList getRelationNodes() { return relationNodes; } public void setRelationNodes(ArrayList relationNodes) { this.relationNodes = relationNodes; } } public boolean isNodeInStack(Node node)/*判斷節(jié)點是否在棧中*/ { Iterator it = stack.iterator(); while(it.hasNext()) { Node node1 = (Node)it.next(); if(node == node1) return true; } return false; } public void showAndSavePath ()/*此時棧中的節(jié)點組成一條所求路徑,轉(zhuǎn)儲并打印輸出*/ { Object[] o = stack.toArray(); for(int i = 0;i<o.length;i++) { System.out.print(o[i]); } sers.add(o); /*轉(zhuǎn)儲*/ System.out.println("\n"); } /*尋找路徑的方法*/ public boolean getPaths(Node cNode, Node pNode, Node sNode, Node eNode) /*cNode表示當前的起始節(jié)點currentNode,pNode表示當前起始節(jié)點的上一節(jié)點previousNode,sNode表示最初的起始節(jié)點startNode,eNode表示終點endNode*/ { Node nNode = null; if(cNode != null && pNode != null && cNode == pNode) return false;/*如果符合條件判斷說明出現(xiàn)環(huán)路,不能再順著該路徑繼續(xù)尋路,返回false*/ if(cNode != null) { int i = 0; stack.push(cNode);/*起始節(jié)點入棧*/ if(cNode == eNode)/*如果該起始節(jié)點就是終點,說明找到一條路徑*/ { showAndSavePath();/*轉(zhuǎn)儲并打印輸出該路徑,返回true*/ return true; } Else/*如果不是,繼續(xù)尋路*/ { nNode = cNode.getRelationNodes().get(i);/*從與當前起始節(jié)點cNode有連接關(guān)系的節(jié)點集中按順序遍歷得到一個節(jié)點作為下一次遞歸尋路時的起始節(jié)點*/ while(nNode != null) { if(pNode != null && (nNode == sNode || nNode == pNode || isNodeInStack(nNode)))/*如果nNode是最初的起始節(jié)點或者nNode就是cNode的上一節(jié)點或者nNode已經(jīng)在棧中,說明產(chǎn)生環(huán)路,應重新在與當前起始節(jié)點有連接關(guān)系的節(jié)點集中尋找nNode*/ { i++; if(i>=cNode.getRelationNodes().size()) nNode = null; else nNode = cNode.getRelationNodes().get(i); continue; } /*以nNode為新的起始節(jié)點,當前起始節(jié)點cNode為上一節(jié)點,遞歸調(diào)用尋路方法*/ if(getPaths(nNode, cNode, sNode, eNode))/*遞歸調(diào)用*/ { stack.pop();/*如果找到一條路徑,則彈出棧頂節(jié)點*/ } i++;/*繼續(xù)在與cNode有連接關(guān)系的節(jié)點集中測試nNode*/ if(i>=cNode.getRelationNodes().size()) nNode = null; else nNode = cNode.getRelationNodes().get(i); } stack.pop();/*當遍歷完所有與cNode有連接關(guān)系的節(jié)點后,說明在以cNode為起始節(jié)點到終點的路徑已經(jīng)全部找到*/ return false; } } else return false; }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java設(shè)計模式之備忘錄模式_動力節(jié)點Java學院
我們在編程的時候,經(jīng)常需要保存對象的中間狀態(tài),當需要的時候,可以恢復到這個狀態(tài)。接下來通過本文給大家分享java設(shè)計模式之備忘錄模式,感興趣的的朋友一起看看吧2017-08-08JAVA中實現(xiàn)原生的 socket 通信機制原理
本篇文章主要介紹了JAVA中實現(xiàn)原生的 socket 通信機制原理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08使用mybatisplus接收mysql字段為json類型的數(shù)據(jù)方式
這篇文章主要介紹了使用mybatisplus接收mysql字段為json類型的數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04詳解SpringCloud新一代網(wǎng)關(guān)Gateway
SpringCloud Gateway是Spring Cloud的一個全新項目,Spring 5.0+ Spring Boot 2.0和Project Reactor等技術(shù)開發(fā)的網(wǎng)關(guān),它旨在為微服務架構(gòu)提供一種簡單有效的統(tǒng)一的API路由管理方式2021-06-06java數(shù)組、泛型、集合在多態(tài)中的使用及對比
本文主要介紹了java數(shù)組、泛型、集合在多態(tài)中的使用及對比。具有很好的參考價值,下面跟著小編一起來看下吧2017-03-03