p354图的DFS(用栈消除递归调用)

来源:互联网 发布:mac dare you日常吗 编辑:程序博客网 时间:2024/05/24 02:57

首先看下面的递归代码,留意每层递归的栈需要保存什么变量

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;}
0 0
原创粉丝点击