首先看下面的递归代码,留意每层递归的栈需要保存什么变量
int dfsvisit(gve G,node *pnode,int *time)
{
edge *tmp=pnode->next;
(*time)++;
pnode->d=*time;
pnode->color=gray;
while (tmp!=NULL)
{
if (G.g[tmp->i].color==white)
dfsvisit(G,&G.g[tmp->i],time);
tmp=tmp->next;
}
pnode->color=black;
(*time)++;
pnode->f=*time;
return 0;
}
- 递归呢,就是一个函数不断调用自身,直到满足递归终止条件而返回。系统在一个递归调用过程中,首先是将当前递归层的局部变量保存在当前栈里面,再将下一层递归的变量入栈;当下一层递归退出的时候,从栈中读取恢复这些局部变量,准备根据新的情况再进行操作(有可能又是递归调用);如果当前递归层的操作都做完了,系统就会出栈,要返回值的也在这个时候返回
那么对照着上面的代码看:
- 首先看参数:
- gve G,递归过程中并没有变化,相当于全局变量
- node *pnode, 每层递归都不一样,需要保存在栈里面
- int *time,时间戳,对递归来说是全局变量
- 再看局部变量:
- edge *tmp,函数会对和点相连的边逐一探索,每探索一次tmp的值都会发生变化,因此需要用栈来保存
- 这样需要保存在栈里面的数据就确定了,pnode和tmp
- 接下来是如何控制递归过程,分析while循环
- 首先从栈里面恢复tmp,继续寻找下一条可用的边
- then语句:如果没有可用的边了,准备出栈,从栈中恢复pnode,修改该点的属性(实际上pnode只在出栈的时候用得上)
- else语句:如果有可用边,将tmp保存在栈里面,便于下次恢复,将下一层递归需要的参数入栈
下面这段代码可以完全替代上面的代码
typedef struct stack_element{
node *pnode;
edge *tmp;
}stack_element;
typedef struct stack{
int size,tail;
stack_element *head;
}stack;
int push(stack *visit_stack,node *pnode,edge *tmp)
{
if (visit_stack->tail==visit_stack->size-1)
{
printf("stack overflow!\n");
return 0;
}
visit_stack->tail++;
visit_stack->head[visit_stack->tail].pnode=pnode;
visit_stack->head[visit_stack->tail].tmp=tmp;
return 0;
}
int pop(stack *visit_stack)
{
visit_stack->tail--;
return 0;
}
int dfsvisit(gve G,node *pnode,int *time)
{
stack visit_stack;
visit_stack.size=G.v;
visit_stack.tail=-1;
visit_stack.head=(stack_element *)malloc(sizeof(stack_element)*(G.v));
edge *tmp=pnode->next;
(*time)++;
pnode->d=*time;
pnode->color=gray;
push(&visit_stack,pnode,tmp);
while (visit_stack.tail!=-1)
{
tmp=visit_stack.head[visit_stack.tail].tmp;
while ((tmp!=NULL)&&(G.g[tmp->i].color!=white))
tmp=tmp->next;
if (tmp==NULL)
{
pnode=visit_stack.head[visit_stack.tail].pnode;
pnode->color=black;
(*time)++;
pnode->f=*time;
pop(&visit_stack);
}
else
{
visit_stack.head[visit_stack.tail].tmp=tmp;
push(&visit_stack,&G.g[tmp->i],G.g[tmp->i].next);
(*time)++;
visit_stack.head[visit_stack.tail].pnode->d=*time;
visit_stack.head[visit_stack.tail].pnode->color=gray;
}
}
free(visit_stack.head);
return 0;
}