这里代码写的比较随意,直接使用数组下标作为索引,而结点就是用0到n-1来表示。
类似于递归调用的思想(感觉就是把递归调用里面的调用栈用简单的栈数组来替代一下)。这里对于栈顶的元素,如果它为白色,则全局时间变量加一,且把它邻接链表里的白色节点全部入栈;而如果栈顶元素已经是灰色,就把它变成黑色,时间全局变量加一,并且出栈;如果栈顶元素是黑丝,直接出栈。(这里黑色是必须的,因为结点可能重复入栈)
时间计算:每个循环要么有黑色结点出栈,要么时间变量加一,所以运行时间为Θ(V+E),因为所有入栈的结点数不会超过邻接链表的总大小。
分析一下两个时间戳和父节点的赋值:
1) v.d是第一次探索这个节点的时间,即把它从白色变成灰色的时候对v.d进行赋值。
2) v.f是该结点的所有结点都被探索过后,即把它从灰色变为黑色的时候对v.f进行赋值。
3) v.pi在入栈的时候赋值。
PS:网上搜了一下,发现有个方法是一个结点入栈就break,并对这个结点作处理。本质上没有太大区别,我这里使用较大的栈空间,而那种方法期望时间比较长。
#include <stdio.h> #define N 100 typedef struct Vertex { int color; int pi; int d; int f; int index;//下标 }Vertex; typedef struct Node{ int index;//对应的结点的数组下标,相当于存储了该结点的指针 struct Node *next; }Node; typedef struct List{ Node *head; }List; int stack[N]; static int count = 0; int time=0; void DFS_V(List *Adj, Vertex *V, int n, int u); void DFS(List *Adj,Vertex *V,int n){ for (int i = 0; i < n; ++i){ V[i].color = 0; V[i].pi = -1; } for (int i = 0; i < n; ++i){ if (V[i].color == 0) DFS_V(Adj,V, n, i); } } void DFS_V(List *Adj, Vertex *V,int n, int u){ stack[count++] = u; while (count){ int v = stack[count - 1]; if (V[v].color == 0){ V[v].color = 1; ++time; V[v].d = time; Node *tmp = Adj[v].head; while (tmp){ if (V[tmp->index].color == 0) { stack[count++] = tmp->index; V[tmp->index].pi = v; } tmp = tmp->next; } } else if (V[v].color==1){ V[v].color = 2; ++time; V[v].f = time; --count; } else --count; } } void print(Vertex *v,int n){ for (int i = 0; i <n; i++){ printf("%d %d %d ", v[i].d, v[i].f,v[i].pi); } } void print_a(List *adj, int n){ for (int i = 0; i < n; ++i){ Node *tmp = adj[i].head; while (tmp){ printf("%d", tmp->index); tmp = tmp->next; } printf(" "); } } int main(){ Vertex V[6]; for (int i = 0; i < 6; ++i) V[i].index = i; List Adj[6] = { 0, 0, 0, 0, 0, 0 }; /*while (1){ int u, v; cin >> u >> v; if (u < 0) break; Node tmp = { v, Adj[u].head }; Adj[u].head = &tmp; } */ Node n1 = { 2, 0 }, n2 = { 1, &n1 }, n11 = {4,&n2}; Adj[0].head = &n11; Node n3 = { 0, 0 }, n4 = { 4, &n3 }, n5 = { 3, &n4 }; Adj[1].head = &n5; Node n6 = { 0, 0 }, n7 = { 5, &n6 }; Adj[2].head = &n7; Node n8 = { 1, 0 }; Adj[3].head = &n8; Node n9 = { 1, 0 }; Adj[4].head = &n9; Node n10 = { 2, 0 }; Adj[5].head = &n10; print_a(Adj, 6); DFS(Adj, V, 6); print(V, 6); }