Bien, esta es mi primera publicación en Desbordamiento de pila He estado leyendo durante un tiempo y realmente admiro el sitio. Espero que esto sea algo que sea aceptable preguntar. Así que he estado leyendo Intro to Algorithms (Cormen, MIT Press) todo el tiempo y estoy a la altura de los algoritmos de gráficos. He estado estudiando los algoritmos formales establecidos para la primera búsqueda de amplitud y profundidad con gran detalle.Profundidad no recursiva-Primera búsqueda (DFS) Uso de una pila
Aquí es el pseudo-código dado para búsqueda en profundidad:
DFS(G)
-----------------------------------------------------------------------------------
1 for each vertex u ∈ G.V
2 u.color ← WHITE // paint all vertices white; undiscovered
3 u.π ← NIL
4 time ← 0 // global variable, timestamps
5 for each vertex u ∈ G.V
6 if u.color = WHITE
7 DFS-VISIT(G,u)
DFS-VISIT(G, u)
-----------------------------------------------------------------------------------
1 u.color ← GRAY // grey u; it is discovered
2 time ← time + 1
3 u.d ← time
4 for each v ∈ G.Adj[u] // explore edge (u,v)
5 if v.color == WHITE
6 v.π ← u
7 DFS-VISIT(G,v)
8 u.color ← BLACK // blacken u; it is finished
9 time ← time + 1
10 u.f ← time
Este algoritmo es recursiva y que procede de varias fuentes (será descubierto cada vértice en el gráfico sin conectar). Tiene varias propiedades que la mayoría de las implementaciones específicas del lenguaje pueden omitir. Se distingue entre 3 diferentes 'colores' de vértices. Inicialmente los pinta en blanco, luego cuando son 'descubiertos' (visitados en DFS-VISIT) se pintan de gris. El algoritmo DFS-VISIT ejecuta un bucle llamada recursivamente a sí mismo en la lista de adyacencia del vértice actual y solo pinta un vértice negro cuando no tiene más bordes a ningún nodo blanco.
También se mantienen otros dos atributos de cada vértice u.d y u.f son los sellos de tiempo para cuando se descubrió el vértice (pintado de gris) o cuando se terminó un vértice (pintado de negro). La primera vez que se pinta un nodo, tiene un sello de tiempo de uno y se incrementa al siguiente valor entero para cada vez que se pinta otro (ya sea gris o negro). u.π también se mantiene, que es solo un puntero al nodo desde el que se descubrió.
Algorithm Non-Recursive-DFS(G)
-----------------------------------------------------------------------------------
1 for each vertex u ∈ G.V
2 u.color ← WHITE
3 u.π ← NIL
4 time = 0
5 for each vertex u ∈ G.V
6 if u.color = WHITE
7 u.color ← GRAY
8 time ← time + 1
9 u.d ← time
7 push(u, S)
8 while stack S not empty
9 u ← pop(S)
10 for each vertex v ∈ G.Adj[u]
11 if v.color = WHITE
12 v.color = GRAY
13 time ← time + 1
14 v.d ← time
15 v.π ← u
16 push(v, S)
17 u.color ← BLACK
18 time ← time + 1
19 u.f ← time
* * EDITAR 31/10/12 Esto es embarazoso que mi algoritmo ha sido incorrecta durante tanto tiempo, que funcionaría en la mayoría de los casos, pero no todos. Acabo de recibir un distintivo de pregunta popular para la pregunta y vi dónde había visto Irfy el problema en su respuesta a continuación, así que ahí es donde va el mérito. Solo lo estoy arreglando aquí para cualquiera que necesite esto en el futuro.
¿Alguien ve una falla con el algoritmo anterior? No soy, con mucho, un experto en teoría de grafos, pero creo que tengo una buena comprensión de la recursión y la iteración y creo que esto debería funcionar de la misma manera. Estoy buscando hacerlo funcionalmente equivalente al algoritmo recursivo. Debe mantener todos los atributos del primer algoritmo, incluso si no son necesarios.
Cuando comencé a escribirlo no pensé que tendría un ciclo triple, pero así fue. He visto otros algoritmos iterativos cuando busqué en Google que solo tienen un bucle doblemente anidado, sin embargo, no parecen proceder de múltiples fuentes. (es decir, no descubrirán todos los vértices del gráfico no conectado)
Corrija la sangría después de la instrucción 'if' en el segundo ciclo en el segundo algoritmo. Lo ideal sería también la sangría después del primer bucle 'for' – Irfy
Realicé la edición justo ahora, esto es lo que tenía originalmente. –
Los tiempos de finalización calculados por la versión no recursiva serán incorrectos. u.f <-time solo se puede establecer después de que todos los descendientes hayan configurado su hora de finalización. Si se toma el mismo ejemplo en CLRS, entonces el nodo u tendría un tiempo de finalización = 3, mientras que el valor real debería haber sido 8. –