Поиск и печать узлов в цикле или в тупике на основе DFS в неориентированном графе

#python #depth-first-search #cycle #undirected-graph

#python #поиск в глубину #цикл #неориентированный граф

Вопрос:

У меня есть упражнение для университета, где я должен написать расширенный алгоритм DFS. На основе DFS я должен указать процедуру, которая пересекает неориентированный непрерывный граф, классифицируя каждый узел в соответствии с тем, является ли он частью цикла или тупиком, и печатать узлы, которые находятся в цикле или в тупике. Эта процедура должна быть применена к графам, показанным с помощью начального узла S. Нарисованный граф

У меня есть следующий список смежности:

 'S' : ['A']
'A' : ['B','F']
'B' : ['C','H']
'C' : ['D','B']
'D' : ['C','E','G']
'E' : ['D','F']
'F' : ['A','E']
'G' : ['D']
'H' : ['B','I']
'I' : ['H']
  

Я сопоставил каждый узел со следующими номерами:

 0: S
1: A
2: B
3: C
4: D
5: E
6: F
7: G
8: H
9: I
  

Вот код, который я написал до сих пор для обнаружения цикла в графе (отредактированный):

 
# Python Program to detect cycle in an undirected graph 
from collections import defaultdict

visitedList = list()
nodes = set()
s = ''


# This class represents a undirected graph using adjacency list representation
class Graph:

    def __init__(self, vertexCount):
        self.V = vertexCount  # No. of vertices
        self.graph = defaultdict(list)  # default dictionary to store graph

    # function to add an edge to graph
    def addEdge(self, v, w):
        self.graph[v].append(w)  # Add w to v_s list
        self.graph[w].append(v)  # Add v to w_s list
        nodes.add(v)
        nodes.add(w)
        # print(self.graph)

    # A recursive function that uses visited[] and parent to detect
    # cycle in subgraph reachable from vertex v.
    def isCyclicUtil(self, v, visited, parent, cycle=list()):
        global s
        visited[v] = True
        visitedList.append(v)
        # Recur for all the vertices adjacent to this vertex
        for i in self.graph[v]:
            # If the node is not visited then recurse on it
            if not visited[i]:
                cycle.append(i)
                if self.isCyclicUtil(i, visited, v, cycle):
                    return
            # If an adjacent vertex is visited and not parent of current vertex,
            # then there is a cycle
            elif parent != i:
                s = 'Nodes in a cycle: '
                s  = ' '.join(str(v) for v in cycle)
                s  = 'nNodes in a dead end: '
                s  = ' '.join(str(v) for v in Diff(nodes, cycle))
                #return
                return True
        return cycle

    # Returns true if the graph contains a cycle, else false.
    def isCyclic(self):
        # Mark all the vertices as not visited
        visited = [False] * (self.V)
        cycle = list()
        # Call the recursive helper function to detect cycle in different 
        # DFS trees
        for i in range(self.V):
            if not visited[i]:  # Don't recur for u if it is already visited
                if self.isCyclicUtil(i, visited, -1, cycle):
                    return True
        return False


def Diff(li1, li2):
    return list(list(set(li1) - set(li2))   list(set(li2) - set(li1)))


# Driver code
# Create a graph with given adjacency list
S = 0
A = 1
B = 2
C = 3
D = 4
E = 5
F = 6
G = 7
H = 8
I = 9

g = Graph(10)

g.addEdge(S, A)
g.addEdge(A, B)
g.addEdge(B, C)
g.addEdge(B, H)
g.addEdge(C, D)
g.addEdge(D, E)
g.addEdge(D, G)
g.addEdge(E, F)
g.addEdge(F, A)
g.addEdge(H, I)


if g.isCyclic():
    print("Graph contains cycle")
    print(s)
else:
    print("Graph does not contain cycle")

'''
g = Graph(6)

g.addEdge(0, 1)
g.addEdge(1, 3)
g.addEdge(1, 2)
g.addEdge(1, 4)
g.addEdge(4, 5)

if g.isCyclic():
    print("Graph contains cycle")
    print(s)
else:
    print("Graph does not contain cycle")
'''
  

Чего здесь еще не хватает, так это печатать узлы, которые находятся в цикле или в тупике.

Комментарии:

1. не сравнивайте логические значения с логической константой, используйте логическое значение или не логическое значение. Нет необходимости () в if выражении (это не C ), если параметром метода является количество вершин, не вызывайте его vertices , но что-то вроде vertexCount , self.V это не очень описательное имя, через 6 месяцев вы будете в замешательстве

2. передайте посещенные заметки в функцию util и верните измененный список, если найден цикл, и распечатайте этот список

3. @rioV8 Я добавил цикл, который я возвращаю при нахождении цикла. Дело в том, что когда я меняю расположение addEdge, он работает некорректно, но также и для другого графика в нижней части кода (см. Мой Отредактированный код).

4. return cycle : непустой список является «истинным», избавьтесь от глобальных переменных, используйте имена узлов, а не сопоставление с числами, никогда не используйте list() аргумент по умолчанию, используйте отладчик, чтобы увидеть, что еще не так в рекурсивной логике