图的深度遍历(邓俊辉版)

本文详细介绍了图的深度优先搜索(DFS)过程中边的四种类型:tree、backward、forward和cross,并通过伪代码展示了如何判断边的类型。在DFS过程中,作者解释了每种边的含义和它们在遍历树中的角色,同时提供了代码实现来标识这些边。文章以一个具体的例子展示了DFS的过程,并输出了边的性质和节点的dtime、ftime信息。
摘要由CSDN通过智能技术生成

一、说在前面

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

邓老师把图的边分成了4种:tree,backward,forward,cross。个人觉得,这样分的意义就在于对遍历树来说,原图的各条边各自有什么意义:
tree:这条边是遍历树的一条树枝。
backward:原图中存在这么一条边:v->u,但是在遍历树中,u是祖先,v是后代,所以在原图中,这就是一条孩子指向祖先的边(大逆不道.jpg),类似于(i)中的G->A。
forward:原图中存在这么一条边:v->u,而且在遍历树中,v是u的祖先,所以叫正向边,类似于(f)中的A->C
cross:原图中存在这么一条边:v->u,但是在遍历树中,v和u没有直接的祖先关系,顶多是兄弟、叔侄关系(比如j中的G->C),甚至来自不同的遍历树(比如(q)中的E->F)(对,一个图用深度遍历时确实可能产生多棵遍历树的)

二、代码实现和输出

这是书上的伪代码
在这里插入图片描述

我把ABCDEFG用1234567来表示了
有向边的输入:

1 2
2 3
1 3
1 6
6 7
7 1
7 3
4 1
4 5
5 6

代码实现

#include <stdio.h>
#define maxn 10

typedef struct node{
    int dtime;
    int ftime;
    int out;
    int discovered;
}node;

typedef node* nodeptr;

int G[maxn][maxn];
node nodes[maxn];
int n=7;//结点的个数
int clock;

//对某个节点进行深度优先搜索
void dfs(int v){
    printf("%d ",v);
    nodes[v].dtime=++clock;
    nodes[v].discovered=1;
    for(int u=1;u<=n;u++){
        if(G[v][u]){
            //如果该节点没有被发现,那么就加入到树中,然后对这个节点继续深度遍历
            if(nodes[u].discovered==0){
                G[v][u]='t';
                dfs(u);
            }
            //如果该节点被发现了,但是u的所有邻居可能还没有被访问完,标志是u节点的ftime是否被赋值了
            else if(nodes[u].ftime==0){
                G[v][u]='b';
            }
            //如果已经被访问完了,那么如果dtime(v)<dtime(u),那么v->u必然是一条祖先指向后代的边;如果dtime(v)>dtime(u),那么v,u必来自两棵独立的分支
            else{
                G[v][u]=nodes[v].dtime<nodes[u].dtime?'f':'c';
            }
        }
    }
    nodes[v].ftime=++clock;
}

//检漏
void DFS(){
    for(int i=1;i<=n;i++){
        if(nodes[i].discovered==0){
            dfs(i);
        }
    }
}

//打印各条有向边的性质,t表示tree,b表示backward,f表示forward,c表示cross
void printArray(){
    printf("\n    ");
    for(int i=1;i<=n;i++){
        printf("%-3d",i);
    }
    printf("\n");
    for(int i=1;i<=n;i++){
        printf("%-4d",i);
        for(int j=1;j<=n;j++){
            printf("%-3c",G[i][j]);
        }
        printf("\n");
    }
}

//打印各个节点的dtime和ftime
void printTime(){
    for(int i=1;i<=n;i++){
        printf("%d: dtime=%d, ftime=%d\n",i,nodes[i].dtime,nodes[i].ftime);
    }
}

int main(){
    int xi,yi;
    int len_num=10;
    //构造邻接矩阵
    for(int i=0;i<len_num;i++){
        scanf("%d%d",&xi,&yi);
        G[xi][yi]=1;
        nodes[xi].out++;
    }
    //如果想要指定从第i个节点开始深度遍历,那么就先调用dfs(i),然后再用DFS()来检查所有节点,确保不漏
    //dfs(i);
    DFS();
    printArray();
    printTime();
}


输出:
在这里插入图片描述
第一行是遍历序列,输出矩阵的时候有乱码,问题不大,是因为我把int型数组全按字符输出了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值