Finn stiene mellom to gitte noder?

stemmer
42

Si jeg har noder koblet på under mote, hvordan jeg kommer til antall baner som eksisterer mellom punktene, og bane detaljer?

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

Finn stiene fra 1 til 7:

Svar: 2 baner funnet, og de er

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

alt

implementering funnet her er fin jeg kommer til å bruke samme

Her er tekstutdrag fra koblingen ovenfor i 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']
Publisert på 03/04/2009 klokken 11:09
kilden bruker
På andre språk...                            


8 svar

stemmer
-3

Hva du prøver å gjøre er egentlig å finne en sti mellom to noder i en (rettet?) Graf sjekke ut Dijkstras algoritme dersom du trenger korteste veien, eller skrive en enkel rekursiv funksjon hvis du trenger det stier eksisterer.

Svarte 03/04/2009 kl. 11:14
kilden bruker

stemmer
33

Bredde-først søk traverserer en graf og faktisk finner alle baner fra en utgangsnode. Vanligvis betyr BFS ikke holde alle veier, men. I stedet oppdaterer det en prededecessor funksjon π for å redde den korteste veien. Du kan enkelt endre algoritmen, slik at π(n)ikke bare lagre en forgjengeren, men en liste over mulige forgjengere.

Da alle mulige veier er kodet i denne funksjonen, og ved å gå gjennom n rekursivt du får alle mulige banekombinasjoner.

En god pseudokode som bruker denne notasjonen kan bli funnet i Introduction to Algorithms av Cormen et al. og har senere blitt brukt i mange Universitetet skript på emnet. Et Google-søk etter “BFS pseudo forgjenger π” uproots dette treffet på Stack Exchange- .

Svarte 03/04/2009 kl. 11:38
kilden bruker

stemmer
1

Hvis du vil at alle banene, bruke rekursjon.

Ved hjelp av en tilstøter liste, fortrinnsvis, å lage en funksjon f () som forsøker å fylle i en aktuell liste over besøkte toppunkter. Som så:

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

På grunn av det faktum at vektoren passeres av verdi (og således eventuelle endringer som er gjort lenger ned i den rekursive prosedyren er ikke permanent), er alle mulige kombinasjoner nummerert.

Du kan få en bit av effektivitet ved å sende forrige vektoren ved henvisning (og dermed ikke ønsker å kopiere vektor om og om igjen), men du må sørge for at ting blir popped_back () manuelt.

En ting til: hvis grafen har sykluser, vil dette ikke fungere. (Jeg antar at i dette tilfellet vil du ønsker å finne alle enkle stier, da) Før du legger noe inn i forrige vektor, først sjekke om det allerede er der.

Hvis du vil at alle korteste stier, bruke Konrad forslag med denne algoritmen.

Svarte 03/04/2009 kl. 11:45
kilden bruker

stemmer
7

Dijkstras algoritme gjelder mer å vektet stier og det høres ut plakaten var ønsker å finne alle veier, ikke bare den korteste.

For dette programmet, vil jeg bygge en graf (søknaden din høres ut som det ikke trenger å være rettet) og bruke din favoritt søkemetode. Det høres ut som du vil at alle veier, ikke bare en gjetning på kortest en, så bruk en enkel rekursiv algoritme av ditt valg.

Det eneste problem med dette er hvis grafen kan være syklisk.

Med tilkoblinger:

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

Mens du leter etter en vei fra 1-> 4, kan du ha en syklus av 1 -> 2 -> 3 -> 1.

I så fall, så jeg ville holde en stabel som krysser nodene. Her er en liste med trinnene for at grafen og den resulterende stabel (beklager for formatering - ingen tabell alternativ):

strømnode (mulige neste noder minus hvor vi kom fra) [stabel]

  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] // feil - duplisere tall på stabelen - syklusen detektert
  5. 3 () [1, 2, 3] // tilbake-trappet til node tre og har oppstått en av stabelen. Ingen flere noder å utforske herfra
  6. 2 (4) [1, 2] // tilbake-trappet til node 2 og har oppstått en av stabelen.
  7. 4 () [1, 2, 4] // Target -node - registrering stabel for en bane. Ingen flere noder å utforske herfra
  8. 2 () [1, 2] // tilbake-trappet til node 2 og spratt 4 av stabelen. Ingen flere noder å utforske herfra
  9. 1 (3) [1] // tilbake-trappet til en node og spratt 2 av stabelen.
  10. 3 (2) [1, 3]
  11. 2 (1, 4) [1, 3, 2]
  12. 1 (2, 3) [1, 3, 2, 1] // feil - duplisere tall på stabelen - syklusen detektert
  13. 2 (4) [1, 3, 2] // tilbake-trappet til node 2 og har oppstått en av stabelen
  14. 4 () [1, 3, 2, 4] Target -node - registrering stabel for en bane. Ingen flere noder å utforske herfra
  15. 2 () [1, 3, 2] // tilbake-trappet til node 2 og spratt 4 av stabelen. Ingen flere noder
  16. 3 () [1, 3] // tilbake-trappet til node 3 og har oppstått to av stabelen. Ingen flere noder
  17. 1 () [1] // tilbake-trappet til en node og spratt 3 av stabelen. Ingen flere noder
  18. Ferdig med 2 innspilte banene for [1, 2, 4] og [1, 3, 2, 4]
Svarte 03/04/2009 kl. 11:52
kilden bruker

stemmer
3

Den opprinnelige koden er litt tungvint, og du vil kanskje bruke den collections.deque i stedet hvis du ønsker å bruke BFS for å finne ut om en bane eksisterer mellom 2 punkter på grafen. Her er en rask løsning jeg hacket opp:

Merk: Denne metoden kan fortsette uendelig hvis det finnes ingen vei mellom to noder. Jeg har ikke testet alle tilfeller, 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)
Svarte 20/07/2009 kl. 02:22
kilden bruker

stemmer
23

For de som ikke er PYTHON ekspert, den samme koden i 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 ]


*/
Svarte 04/06/2012 kl. 19:17
kilden bruker

stemmer
2

gitt naboskapsmatrisen:

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

følgende Wolfram Mathematica kode løse problemet med å finne alle de enkle baner mellom to noder i en graf. Jeg brukte enkle rekursjon, og to global Var å holde styr på sykluser og lagre den ønskede effekt. koden ikke har blitt optimalisert bare for moro skyld kode klarhet. "print" skal være nyttig for å avklare hvordan det fungerer.

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

å kalle inn koden: initNode = 1; endNode = 6; lcycle = {}; treet = {{initNode}}; builtTree [initNode, matrise];

baner: {{1}} rot: 1 --- noder: {2,3,4}

veier: {{1,2}, {1,3}, {1,4}} rot: 2 --- noder: {3,4,5}

veier: {{1,3}, {1,4}, {1,2,3}, {1,2,4}, {1,2,5}} rot: 3 --- noder: {2, 4}

veier: {{1,4}, {1,2,4}, {1,2,5}, {1,3,4}, {1,2,3,4}, {1,3,2, 4}, {1,3,2,5}} rot: 4 --- noder: {2,3,6}

veier: {{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}} rot: 5 --- noder: {6}

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

... Dessverre kan jeg ikke laste opp bilder for å vise resultatene i en bedre måte :(

http://textanddatamining.blogspot.com

Svarte 23/08/2012 kl. 18:58
kilden bruker

stemmer
3

I Prolog (spesifikt, 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).

test:

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.
Svarte 15/09/2016 kl. 12:02
kilden bruker

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