Βρείτε τις διαδρομές μεταξύ δύο δεδομένων κόμβων;

ψήφοι
42

Ας υποθέσουμε ότι έχω κόμβους που συνδέονται στο παρακάτω μόδας, πώς μπορώ να φτάνουν τον αριθμό των διαδρομών που υπάρχουν μεταξύ των δεδομένων σημείων, και λεπτομέρειες πορεία;

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

Βρείτε τις διαδρομές από 1 έως 7:

Απάντηση: 2 μονοπάτια που βρέθηκαν και είναι

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

alt

εφαρμογή που βρέθηκαν εδώ είναι ωραία Πάω να χρησιμοποιούν το ίδιο

Εδώ είναι το απόσπασμα από το παραπάνω link σε 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']
Δημοσιεύθηκε 03/04/2009 στις 12:09
πηγή χρήστη
Σε άλλες γλώσσες...                            


8 απαντήσεις

ψήφοι
-3

Αυτό που προσπαθούμε να κάνουμε είναι ουσιαστικά να βρείτε μια διαδρομή μεταξύ δύο κορυφών σε ένα γράφημα (σκηνοθεσία;) δείτε τον αλγόριθμο του Dijkstra αν χρειάζεστε συντομότερη διαδρομή ή να γράψουν ένα απλό αναδρομική συνάρτηση αν χρειαστεί ό, τι υπάρχουν μονοπάτια.

Απαντήθηκε 03/04/2009 στις 12:14
πηγή χρήστη

ψήφοι
33

Πλάτος αναζήτηση πρώτα διασχίζει ένα γράφημα και στην πραγματικότητα βρίσκει όλα τα μονοπάτια από ένα αρχικό κόμβο. Συνήθως, BFS δεν τηρεί όλες τις διαδρομές, όμως. Αντ 'αυτού, ενημερώνει το π λειτουργία prededecessor να σώσει τη συντομότερη διαδρομή. Μπορείτε εύκολα να τροποποιήσετε τον αλγόριθμο, έτσι ώστε π(n)όχι μόνο να αποθηκεύσει ένα προκατόχου, αλλά μια λίστα των πιθανών προκατόχους.

Στη συνέχεια όλες οι πιθανές διαδρομές που κωδικοποιούνται σε αυτή τη λειτουργία, και από διέρχονται π για αναδρομικά μπορείτε να πάρετε όλους τους πιθανούς συνδυασμούς πορεία.

Ένα καλό ψευδοκώδικας που χρησιμοποιεί αυτό το συμβολισμό μπορεί να βρεθεί στην Εισαγωγή στους Αλγόριθμους από Cormen et al. και στη συνέχεια έχει χρησιμοποιηθεί σε πολλά σενάρια Πανεπιστημίου σχετικά με το θέμα. Μια αναζήτηση στο Google για «BFS ψευδοκώδικα τον προκάτοχό π» ξεριζώνει αυτό το χτύπημα στο Stack Exchange .

Απαντήθηκε 03/04/2009 στις 12:38
πηγή χρήστη

ψήφοι
1

Αν θέλετε όλα τα μονοπάτια, χρησιμοποιήστε αναδρομή.

Χρησιμοποιώντας μια λίστα γειτνίασης, κατά προτίμηση, να δημιουργήσετε μια συνάρτηση f () που προσπαθεί να γεμίσει σε μια τρέχουσα λίστα των επισκέφθηκε κορυφές. Όπως αυτό:

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);
}

Λόγω του γεγονότος ότι ο φορέας έχει περάσει από την αξία (και, επομένως, τυχόν αλλαγές που πραγματοποιούνται περαιτέρω κάτω στην αναδρομική διαδικασία δεν είναι μόνιμοι), όλοι οι πιθανοί συνδυασμοί απαριθμήθηκαν.

Μπορείτε να αποκτήσετε ένα κομμάτι της απόδοσης με το πέρασμα του προηγούμενου φορέα με βάση (και συνεπώς δεν χρειάζεται να αντιγράψετε το φορέα ξανά και ξανά), αλλά θα πρέπει να βεβαιωθείτε ότι τα πράγματα παίρνουν popped_back () με το χέρι.

Και κάτι ακόμα: αν η γραφική παράσταση έχει κύκλους, αυτό δεν θα λειτουργήσει. (Υποθέτω ότι σε αυτή την περίπτωση θα θελήσετε να βρείτε όλες τις απλές διαδρομές, τότε) Πριν από την προσθήκη κάτι στον προηγούμενο φορέα, ελέγξτε πρώτα αν είναι ήδη εκεί.

Αν θέλετε όλα συντομότερο μονοπάτια, χρησιμοποιήστε την πρόταση Konrad με αυτόν τον αλγόριθμο.

Απαντήθηκε 03/04/2009 στις 12:45
πηγή χρήστη

ψήφοι
7

Ο αλγόριθμος του Dijkstra ισχύει περισσότερο για σταθμισμένο μονοπάτια και ακούγεται σαν η αφίσα που θέλουν να βρείτε όλα τα μονοπάτια, όχι μόνο το συντομότερο.

Για την εφαρμογή αυτή, θα ήθελα να οικοδομήσουμε ένα γράφημα (η αίτησή σας ακούγεται σαν δεν θα πρέπει να κατευθύνεται) και να χρησιμοποιήσετε τα αγαπημένα μέθοδο αναζήτησης σας. Ακούγεται σαν να θέλετε όλα τα μονοπάτια, όχι μόνο μια εικασία στο συντομότερο μία, οπότε χρησιμοποιήστε ένα απλό αναδρομικό αλγόριθμο της επιλογής σας.

Το μόνο πρόβλημα με αυτό είναι αν η γραφική παράσταση μπορεί να είναι κυκλική.

Με τις συνδέσεις:

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

Ενώ ψάχνει για ένα μονοπάτι από 1-> 4, θα μπορούσατε να έχετε ένα κύκλο από 1 -> 2 -> 3 -> 1.

Σε αυτή την περίπτωση, τότε θα κρατήσει μια στοίβα και διασχίζει τους κόμβους. Εδώ είναι μια λίστα με τα βήματα για το συγκεκριμένο γράφημα και το προκύπτον στοίβα (συγγνώμη για τη μορφοποίηση - καμία επιλογή πίνακα):

τρέχοντα κόμβο (πιθανή επόμενη κόμβους μείον πού ήρθαμε) [στοίβα]

  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] // σφάλμα - διπλούν αριθμός στη στοίβα - ανιχνεύεται κύκλο
  5. 3 () [1, 2, 3] // επανα-ενταθούν προς τον κόμβο τρεις και έσκασε 1 εκτός της στοίβας. Δεν υπάρχει πλέον κόμβους για να εξερευνήσετε από εδώ
  6. 2 (4) [1, 2] // back-ενισχυθεί σε κόμβο 2 και έσκασε 1 εκτός της στοίβας.
  7. 4 () [1, 2, 4] // κόμβο Target βρέθηκε - εγγραφή στοίβα για μια διαδρομή. Δεν υπάρχει πλέον κόμβους για να εξερευνήσετε από εδώ
  8. 2 () [1, 2] // back-ενισχυθεί σε κόμβο 2 και έσκασε 4 εκτός της στοίβας. Δεν υπάρχει πλέον κόμβους για να εξερευνήσετε από εδώ
  9. 1 (3) [1] // back-ενισχυθεί στον κόμβο 1 και 2 εκτός έσκασε τη στοίβα.
  10. 3 (2) [1, 3]
  11. 2 (1, 4) [1, 3, 2]
  12. 1 (2, 3) [1, 3, 2, 1] // σφάλμα - διπλούν αριθμός στη στοίβα - ανιχνεύεται κύκλο
  13. 2 (4) [1, 3, 2] // επανα-ενισχυθεί σε κόμβο 2 και έσκασε 1 εκτός της στοίβας
  14. 4 () [1, 3, 2, 4] κόμβος Target βρέθηκε - εγγραφή στοίβα για μια διαδρομή. Δεν υπάρχει πλέον κόμβους για να εξερευνήσετε από εδώ
  15. 2 () [1, 3, 2] // back-ενισχυθεί σε κόμβο 2 και έσκασε 4 εκτός της στοίβας. Δεν περισσότερους κόμβους
  16. 3 () [1, 3] // back-ενισχυθεί στον κόμβο 3 και έσκασε 2 εκτός της στοίβας. Δεν περισσότερους κόμβους
  17. 1 () [1] // back-ενισχυθεί στον κόμβο 1 και έσκασε 3 εκτός της στοίβας. Δεν περισσότερους κόμβους
  18. Έγινε με 2 καταγράφεται μονοπάτια της [1, 2, 4] και [1, 3, 2, 4]
Απαντήθηκε 03/04/2009 στις 12:52
πηγή χρήστη

ψήφοι
3

Ο αρχικός κωδικός είναι λίγο περίπλοκη και ίσως να θέλετε να χρησιμοποιήσετε το collections.deque αντ 'αυτού, αν θέλετε να χρησιμοποιήσετε BFS για να βρούμε αν υπάρχει ένα μονοπάτι ανάμεσα σε 2 σημεία στο γράφημα. Εδώ είναι μια γρήγορη λύση που hacked μέχρι:

Σημείωση: αυτή η μέθοδος θα μπορούσε να συνεχιστεί απεριόριστα, αν δεν υπάρχει μονοπάτι μεταξύ των δύο κόμβων. Δεν το έχω δοκιμάσει όλες τις περιπτώσεις, 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)
Απαντήθηκε 20/07/2009 στις 03:22
πηγή χρήστη

ψήφοι
22

Για εκείνους που δεν είναι ειδικός Python, το ίδιο κώδικα σε 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 ]


*/
Απαντήθηκε 04/06/2012 στις 20:17
πηγή χρήστη

ψήφοι
2

δεδομένης της πίνακας γειτνίασης:

{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}

ο κώδικας που ακολουθεί Wolfram Mathematica λύσει το πρόβλημα για να βρείτε όλες τις απλές διαδρομές μεταξύ δύο κόμβων ενός γραφήματος. Θα χρησιμοποιηθεί απλή αναδρομή, και δύο παγκόσμια var για την παρακολούθηση των κύκλων και να αποθηκεύσει το επιθυμητό αποτέλεσμα. ο κώδικας δεν έχει βελτιστοποιηθεί μόνο για χάρη του κώδικα σαφήνειας. η «εκτύπωση» θα πρέπει να είναι χρήσιμο να διευκρινίσει πώς λειτουργεί.

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]]];
    ];
];

για να καλέσετε τον κωδικό: initNode = 1? endNode = 6? lcycle = {}? δέντρο = `initNode`? builtTree [initNode, μήτρα]?

μονοπάτια: `1` ρίζα: 1 --- κόμβους: {2,3,4}

μονοπάτια: {{1,2}, {1,3}, {1,4}} ρίζα: 2 --- κόμβους: {3,4,5}

μονοπάτια: {{1,3}, {1,4}, {1,2,3}, {1,2,4}, {1,2,5}} ρίζα: 3 --- κόμβοι: {2, 4}

μονοπάτια: {{1,4}, {1,2,4}, {1,2,5}, {1,3,4}, {1,2,3,4}, {1,3,2, 4}, {1,3,2,5}} ρίζα: 4 --- κόμβοι: {2,3,6}

μονοπάτια: {{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}} ρίζα: 5 --- κόμβους: {6}

ΑΠΟΤΕΛΕΣΜΑΤΑ: {{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}}

... Δυστυχώς δεν μπορώ να ανεβάσετε εικόνες για να δείτε τα αποτελέσματα σε έναν καλύτερο τρόπο :(

http://textanddatamining.blogspot.com

Απαντήθηκε 23/08/2012 στις 19:58
πηγή χρήστη

ψήφοι
3

Στην Prolog (συγκεκριμένα, 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).

δοκιμή:

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.
Απαντήθηκε 15/09/2016 στις 12:02
πηγή χρήστη

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