Finden Sie die Pfade zwischen zwei gegebenen Knoten?

stimmen
42

Sagen wir, ich Knoten in der unten Art und Weise verbunden haben, wie kann ich bei der Anzahl von Pfaden gelangen, die zwischen Punkten existieren, und Pfadangaben?

1,2 //node 1 and 2 are connected
2,3
2,5
4,2
5,11
11,12
6,7
5,6
3,6
6,8
8,10
8,9

Die Bahnen 1 bis 7:

Antwort: 2 Wege gefunden und sie sind

1,2,3,6,7
1,2,5,6,7

Alt-Text

gefunden Umsetzung hier ist schön , ich das gleiche verwenden , werde

Hier ist der Ausschnitt aus dem obigen Link in Python

# a sample graph
graph = {'A': ['B', 'C','E'],
             'B': ['A','C', 'D'],
             'C': ['D'],
             'D': ['C'],
             'E': ['F','D'],
             'F': ['C']}

class MyQUEUE: # just an implementation of a queue

    def __init__(self):
        self.holder = []

    def enqueue(self,val):
        self.holder.append(val)

    def dequeue(self):
        val = None
        try:
            val = self.holder[0]
            if len(self.holder) == 1:
                self.holder = []
            else:
                self.holder = self.holder[1:]   
        except:
            pass

        return val  

    def IsEmpty(self):
        result = False
        if len(self.holder) == 0:
            result = True
        return result


path_queue = MyQUEUE() # now we make a queue


def BFS(graph,start,end,q):

    temp_path = [start]

    q.enqueue(temp_path)

    while q.IsEmpty() == False:
        tmp_path = q.dequeue()
        last_node = tmp_path[len(tmp_path)-1]
        print tmp_path
        if last_node == end:
            print VALID_PATH : ,tmp_path
        for link_node in graph[last_node]:
            if link_node not in tmp_path:
                #new_path = []
                new_path = tmp_path + [link_node]
                q.enqueue(new_path)

BFS(graph,A,D,path_queue)

-------------results-------------------
['A']
['A', 'B']
['A', 'C']
['A', 'E']
['A', 'B', 'C']
['A', 'B', 'D']
VALID_PATH :  ['A', 'B', 'D']
['A', 'C', 'D']
VALID_PATH :  ['A', 'C', 'D']
['A', 'E', 'F']
['A', 'E', 'D']
VALID_PATH :  ['A', 'E', 'D']
['A', 'B', 'C', 'D']
VALID_PATH :  ['A', 'B', 'C', 'D']
['A', 'E', 'F', 'C']
['A', 'E', 'F', 'C', 'D']
VALID_PATH :  ['A', 'E', 'F', 'C', 'D']
Veröffentlicht am 03/04/2009 um 12:09
quelle vom benutzer
In anderen Sprachen...                            


8 antworten

stimmen
-3

Was Sie versuchen zu tun ist , im Wesentlichen einen Pfad zwischen zwei Knoten in einem zu finden (gerichtet?) Graph Besuchen Dijkstra-Algorithmus , wenn Sie kürzesten Weg benötigen oder eine einfache rekursive Funktion schreiben , wenn Sie brauchen , was Pfade existieren.

Beantwortet am 03/04/2009 um 12:14
quelle vom benutzer

stimmen
33

Breitensuche durchläuft ein Diagramm und in der Tat findet alle Pfade von einem Startknoten. Normalerweise ist BFS nicht alle Pfade halten, jedoch. Stattdessen aktualisiert es eine prededecessor Funktion π den kürzesten Weg zu retten. Sie können den Algorithmus leicht ändern , so dass π(n)nicht nur speichern , ein Vorgänger aber eine Liste der möglichen Vorgänger.

Dann werden alle möglichen Pfade werden in dieser Funktion codiert und durch das Durchlaufen rekursiv ¸ Sie alle möglichen Kombinationen Weg bekommen.

Ein guter Pseudo - Code , der diese Schreibweise verwendet finden Sie in Introduction to Algorithms von Cormen et al. und hat in der Folge in vielen Universitäts Skripte zum Thema verwendet. Eine Google - Suche nach „BFS Pseudo - Code Vorgänger π“ entwurzelt diesen Erfolg auf Stapel von Exchange .

Beantwortet am 03/04/2009 um 12:38
quelle vom benutzer

stimmen
1

Wenn Sie alle Pfade möchten, verwenden Rekursion.

Verwendung eines Adjazenzliste schaffen vorzugsweise eine Funktion f (), die in einer aktuellen Liste der besuchten Vertices zu füllen versucht. Wie so:

void allPaths(vector<int> previous, int current, int destination)
{
    previous.push_back(current);

    if (current == destination)
        //output all elements of previous, and return

    for (int i = 0; i < neighbors[current].size(); i++)
        allPaths(previous, neighbors[current][i], destination);
}

int main()
{
    //...input
    allPaths(vector<int>(), start, end);
}

Aufgrund der Tatsache, dass der Vektor von Wert übergeben wird (und damit weiter nach unten in die rekursive Prozedur werden alle Änderungen sind nicht permanent), alle möglichen Kombinationen werden aufgezählt.

Sie können ein wenig Effizienz gewinnen durch die vorbeizieh vorherigen Vektor durch Referenz (und brauchen somit nicht den Vektor immer und immer wieder zu kopieren) , aber Sie werden dafür sorgen, dass die Dinge popped_back () von Hand zu bekommen.

Eine weitere Sache: wenn der Graph Zyklen hat, wird dies nicht funktionieren. (Ich gehe davon aus in diesem Fall , dass Sie mögen , werden alle finden , einfache Wege, dann) Bevor etwas in das Hinzufügen von vorherigen Vektor, zunächst zu überprüfen , ob es schon drin.

Wenn Sie alle wollen kürzesten Pfade verwenden Konrad Vorschlag mit diesem Algorithmus.

Beantwortet am 03/04/2009 um 12:45
quelle vom benutzer

stimmen
7

Dijkstra-Algorithmus gilt mehr auf gewichtete Pfade und es klingt wie das Plakat fehlte alle Wege zu finden, die nicht nur die kürzeste.

Für diese Anwendung würde ich ein Graph bauen (Ihre Anwendung klingt wie wäre es nicht gerichtet werden muß) und Ihre Lieblingssuchmethode verwenden. Es klingt wie Sie alle Pfade wollen, nicht nur eine Vermutung am kürzesten, so einen einfachen rekursiven Algorithmus Ihrer Wahl verwenden.

Das einzige Problem dabei ist, wenn der Graph zyklisch sein kann.

Mit den Verbindungen:

  • 1, 2
  • 1, 3
  • 2, 3
  • 2, 4

Während für einen Weg von 1-> 4 sucht, könnten Sie einen Zyklus von 1 haben -> 2 -> 3 -> 1.

In diesem Fall ist, dann würde ich einen Stapel halten, wie die Knoten durchqueren. Hier ist eine Liste mit den Schritten für die grafische Darstellung und die sich ergebende Stapel (sorry für die Formatierung - keine Tabellenoption):

Stromknoten (möglicher nächster Knoten minus woher wir kamen) [stack]

  1. 1 (2, 3) [1]
  2. 2 (3, 4) [1, 2]
  3. 3 (1) [1, 2, 3]
  4. 1 (2, 3) [1, 2, 3, 1] // Fehler - duplizieren Nummer auf der Stack - Zyklus erfaßt
  5. 3 () [1, 2, 3] // zurück gestuft drei zum Knoten und tauchte 1 vom Stapel. Nicht mehr Knoten von hier zu erkunden
  6. 2 (4) [1, 2] // zurück gestufte zu Knoten 2 und tauchte 1 vom Stapel.
  7. 4 () [1, 2, 4] // Zielknoten gefunden - Datensatz Stapel für einen Pfad. Nicht mehr Knoten von hier zu erkunden
  8. 2 () [1, 2] // zurück gestufte zu Knoten 2 und 4 aufgetaucht aus dem Stapel. Nicht mehr Knoten von hier zu erkunden
  9. 1 (3) [1] // zurück gestuft zu Knoten 1 und 2 aufgetaucht aus dem Stapel.
  10. 3 (2) [1, 3]
  11. 2 (1, 4) [1, 3, 2]
  12. 1 (2, 3) [1, 3, 2, 1] // Fehler - duplizieren Nummer auf der Stack - Zyklus erfaßt
  13. 2 (4) [1, 3, 2] //-trat zurück 2 und 1 aus dem Stapel geholt zu Knoten
  14. 4 () [1, 3, 2, 4] Zielknoten gefunden - Datensatz Stapel für einen Pfad. Nicht mehr Knoten von hier zu erkunden
  15. 2 () [1, 3, 2] // zurück gestufte zu Knoten 2 und 4 aufgetaucht aus dem Stapel. Keine weiteren Knoten
  16. 3 () [1, 3] // zurück gestufte zu Knoten 3 und tauchte 2 vom Stapel. Keine weiteren Knoten
  17. 1 () [1] // zurück gestuft zu Knoten 1 und tauchten 3 vom Stapel. Keine weiteren Knoten
  18. Geschehen mit 2 aufgezeichneten Pfaden von [1, 2, 4] und [1, 3, 2, 4]
Beantwortet am 03/04/2009 um 12:52
quelle vom benutzer

stimmen
3

Der ursprüngliche Code ist ein bisschen umständlich und man könnte die collections.deque stattdessen verwenden möchten, wenn Sie wollen BFS verwenden zu finden, wenn ein Pfad zwischen zwei Punkten auf dem Graphen existiert. Hier ist eine schnelle Lösung, die ich gehackt:

Hinweis: Diese Methode könnte unendlich fortgesetzt werden, wenn es keinen Weg zwischen den beiden Knoten vorhanden ist. Ich habe nicht alle Fälle getestet, YMMV.

from collections import deque

# a sample graph
  graph = {'A': ['B', 'C','E'],
           'B': ['A','C', 'D'],
           'C': ['D'],
           'D': ['C'],
           'E': ['F','D'],
           'F': ['C']}

   def BFS(start, end):
    """ Method to determine if a pair of vertices are connected using BFS

    Args:
      start, end: vertices for the traversal.

    Returns:
      [start, v1, v2, ... end]
    """
    path = []
    q = deque()
    q.append(start)
    while len(q):
      tmp_vertex = q.popleft()
      if tmp_vertex not in path:
        path.append(tmp_vertex)

      if tmp_vertex == end:
        return path

      for vertex in graph[tmp_vertex]:
        if vertex not in path:
          q.append(vertex)
Beantwortet am 20/07/2009 um 03:22
quelle vom benutzer

stimmen
22

Für diejenigen, die nicht PYTHON Experte sind, der gleiche Code in C ++

//@Author :Ritesh Kumar Gupta
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;
vector<vector<int> >GRAPH(100);
inline void print_path(vector<int>path)
{
    cout<<"[ ";
    for(int i=0;i<path.size();++i)
    {
        cout<<path[i]<<" ";
    }
    cout<<"]"<<endl;
}
bool isadjacency_node_not_present_in_current_path(int node,vector<int>path)
{
    for(int i=0;i<path.size();++i)
    {
        if(path[i]==node)
        return false;
    }
    return true;
}
int findpaths(int source ,int target ,int totalnode,int totaledge )
{
    vector<int>path;
    path.push_back(source);
    queue<vector<int> >q;
    q.push(path);

    while(!q.empty())
    {
        path=q.front();
        q.pop();

        int last_nodeof_path=path[path.size()-1];
        if(last_nodeof_path==target)
        {
            cout<<"The Required path is:: ";
            print_path(path);
        }
        else
        {
            print_path(path);
        }

        for(int i=0;i<GRAPH[last_nodeof_path].size();++i)
        {
            if(isadjacency_node_not_present_in_current_path(GRAPH[last_nodeof_path][i],path))
            {

                vector<int>new_path(path.begin(),path.end());
                new_path.push_back(GRAPH[last_nodeof_path][i]);
                q.push(new_path);
            }
        }




    }
    return 1;
}
int main()
{
    //freopen("out.txt","w",stdout);
    int T,N,M,u,v,source,target;
    scanf("%d",&T);
    while(T--)
    {
        printf("Enter Total Nodes & Total Edges\n");
        scanf("%d%d",&N,&M);
        for(int i=1;i<=M;++i)
        {
            scanf("%d%d",&u,&v);
            GRAPH[u].push_back(v);
        }
        printf("(Source, target)\n");
        scanf("%d%d",&source,&target);
        findpaths(source,target,N,M);
    }
    //system("pause");
    return 0;
}

/*
Input::
1
6 11
1 2 
1 3
1 5
2 1
2 3
2 4
3 4
4 3
5 6
5 4
6 3
1 4

output:
[ 1 ]
[ 1 2 ]
[ 1 3 ]
[ 1 5 ]
[ 1 2 3 ]
The Required path is:: [ 1 2 4 ]
The Required path is:: [ 1 3 4 ]
[ 1 5 6 ]
The Required path is:: [ 1 5 4 ]
The Required path is:: [ 1 2 3 4 ]
[ 1 2 4 3 ]
[ 1 5 6 3 ]
[ 1 5 4 3 ]
The Required path is:: [ 1 5 6 3 4 ]


*/
Beantwortet am 04/06/2012 um 20:17
quelle vom benutzer

stimmen
2

die Adjazenzmatrix gegeben:

{0, 1, 3, 4, 0, 0}

{0, 0, 2, 1, 2, 0}

{0, 1, 0, 3, 0, 0}

{0, 1, 1, 0, 0, 1}

{0, 0, 0, 0, 0, 6}

{0, 1, 0, 1, 0, 0}

der folgende Wolfram Mathematica Code das Problem zu lösen, alle einfachen Pfade zwischen zwei Knoten eines Graphen zu finden. Ich verwenden einfache Rekursion, und zwei globale var Spur von Zyklen zu halten und die gewünschte Ausgabe zu speichern. Der Code wurde nur aus Gründen der Klarheit des Codes nicht optimiert. der „Druck“ sollte hilfreich sein, zu klären, wie es funktioniert.

cycleQ[l_]:=If[Length[DeleteDuplicates[l]] == Length[l], False, True];
getNode[matrix_, node_]:=Complement[Range[Length[matrix]],Flatten[Position[matrix`node`, 0]]];

builtTree[node_, matrix_]:=Block[{nodes, posAndNodes, root, pos},
    If[{node} != {} && node != endNode ,
        root = node;
        nodes = getNode[matrix, node];
        (*Print["root:",root,"---nodes:",nodes];*)

        AppendTo[lcycle, Flatten[{root, nodes}]];
        If[cycleQ[lcycle] == True,
            lcycle = Most[lcycle]; appendToTree[root, nodes];,
            Print["paths: ", tree, "\n", "root:", root, "---nodes:",nodes];
            appendToTree[root, nodes];

        ];
    ];

appendToTree[root_, nodes_] := Block[{pos, toAdd},
    pos = Flatten[Position[tree[[All, -1]], root]];
    For[i = 1, i <= Length[pos], i++,
        toAdd = Flatten[Thread[{tree[[pos`i`]], {#}}]] & /@ nodes;
        (* check cycles!*)            
        If[cycleQ[#] != True, AppendTo[tree, #]] & /@ toAdd;
    ];
    tree = Delete[tree, {#} & /@ pos];
    builtTree[#, matrix] & /@ Union[tree[[All, -1]]];
    ];
];

rufen den Code: initNode = 1; Endknoten = 6; LCYCLE = {}; Baum = `initNode`; builtTree [initNode, matrix];

Wege: '1' root: 1 --- Knoten: {2,3,4}

Wege: {{1,2}, {1,3}, {1,4}} root: 2 --- Knoten: {3,4,5}

Wege: {{1,3}, {1,4}, {1,2,3}, {1,2,4}, {1,2,5}} root: 3 --- Knoten: {2, 4}

Wege: {{1,4}, {1,2,4}, {1,2,5}, {1,3,4}, {1,2,3,4}, {1,3,2, 4}, {1,3,2,5}} root: 4 --- Knoten: {2,3,6}

Wege: {{1,2,5}, {1,3,2,5}, {1,4,6}, {1,2,4,6}, {1,3,4,6}, { 1,2,3,4,6}, {1,3,2,4,6}, {1,4,2,5}, {1,3,4,2,5}, {1,4, 3,2,5}} root: 5 --- Knoten: {6}

ERGEBNISSE: {{1, 4, 6}, {1, 2, 4, 6}, {1, 2, 5, 6}, {1, 3, 4, 6}, {1, 2, 3, 4, 6}, {1, 3, 2, 4, 6}, {1, 3, 2, 5, 6}, {1, 4, 2, 5, 6}, {1, 3, 4, 2, 5, 6}, {1, 4, 3, 2, 5, 6}}

... Leider kann ich keine Bilder hochladen, die Ergebnisse in einer besseren Art und Weise zeigen :(

http://textanddatamining.blogspot.com

Beantwortet am 23/08/2012 um 19:58
quelle vom benutzer

stimmen
3

In Prolog (insbesondere SWI-Prolog)

:- use_module(library(tabling)).

% path(+Graph,?Source,?Target,?Path)
:- table path/4.

path(_,N,N,[N]).
path(G,S,T,[S|Path]) :-
    dif(S,T),
    member(S-I, G), % directed graph
    path(G,I,T,Path).

Prüfung:

paths :- Graph =
    [ 1- 2  % node 1 and 2 are connected
    , 2- 3 
    , 2- 5 
    , 4- 2 
    , 5-11
    ,11-12
    , 6- 7 
    , 5- 6 
    , 3- 6 
    , 6- 8 
    , 8-10
    , 8- 9
    ],
    findall(Path, path(Graph,1,7,Path), Paths),
    maplist(writeln, Paths).

?- paths.
[1,2,3,6,7]
[1,2,5,6,7]
true.
Beantwortet am 15/09/2016 um 12:02
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more