Sir zach

专注于算法,AI, Android以及音视频领域 欢迎关注我的最新博客: zachliu.cn

导航

图算法之DFS

Posted on 2014-08-11 23:07  SirZach  阅读(376)  评论(0编辑  收藏  举报

深度优先搜索(Depth  First Search),类似于树的前序遍历,搜索模型是栈,运用的是递归思想,以下面的无向图为例:

DFSBFS_thumb_thumb

 

伪代码实现如下:

其中u 为 v 的先辈或父母。


DFS(G)

 for each vertex u ∈ V [G]
       do color[u] ← WHITE
          π[u] ← NIL //第1-3行,把所有顶点置为白色,所有π 域被初始化为NIL。
 time ← 0       //复位时间计数器
 for each vertex u ∈ V [G]
       do if color[u] = WHITE
             then DFS-VISIT(u)  //调用DFS-VISIT访问u,u成为深度优先森林中一棵新的树
    //第5-7行,依次检索V中的顶点,发现白色顶点时,调用DFS-VISIT访问该顶点。每个顶点u 都对应于一个发现时刻d[u]和一个完成时刻f[u]。

 

DFS-VISIT(u)

color[u] ← GRAY           
time ← time +1             
d[u] ← time                   //记录u被发现的时间
for each v ∈ Adj[u]   //检查并访问 u 的每一个邻接点 v
       do if color[v] = WHITE            //如果v 为白色,则递归访问v。
             then π[v] ← u                   //置u为 v的先辈
                    DFS-VISIT(v)        
color[u] ← BLACK         //u 置为黑色,表示u及其邻接点都已访问完成
f [u] ← time ← time +1  //访问完成时间记录在f[u]中。

实验环境为ubuntu14.04 x86

  邻接表实现:

#include <stdio.h>
#include <malloc.h>

#define MAX_VERTEX_NUM 50 

typedef char vertexType;
typedef int edgeType;

/* 边表 */
typedef struct ArcNode
{
    int adjIndex;
    ArcNode *nextArc;  
    edgeType weight;
}ArcNode;

/* 顶点表 */
typedef struct VNode
{
    vertexType data;
    ArcNode *firstArc;
}VNode, AdjList[MAX_VERTEX_NUM];

/* 图结构 */
typedef struct
{
    AdjList adjList;
    int vexNum;
    int edgeNum;
}ALGraph;

int visit[MAX_VERTEX_NUM] = {0};

void DFS(ALGraph *G, int i)
{
    visit[i] = 1;

    printf("%c ", G->adjList[i].data);

    ArcNode *arcNodePt = G->adjList[i].firstArc;
    while (arcNodePt)
    {
        if (!visit[arcNodePt->adjIndex])
        {
            DFS(G, arcNodePt->adjIndex);
        }
        arcNodePt = arcNodePt->nextArc;
    }
    // printf("recursion back\n");
}

void DFSTraverse(ALGraph *G)
{
    int i;

    // for (i = 0; i < G->vexNum; i++)
    // {
    //     visit[i] = 0;
    // }

    for (i = 0; i < G->vexNum; i++)
    {
        if (!visit[i])
        {
            DFS(G, i);
        }
    }
}

void CreateALGraph(ALGraph *G)
{
    int i, j, k;
    ArcNode *e;
    int c;

    printf("输入顶点数和边数:\n");
    scanf("%d %d", &G->vexNum, &G->edgeNum);
    setbuf(stdin, NULL);

    for (i = 0; i < G->vexNum; i++)
    {
        printf("输入顶点信息:\n");
        scanf("%c", &G->adjList[i].data);
        G->adjList[i].firstArc = NULL;

        while((c = getchar()) != '\n' && c != EOF);
    }

    for (k = 0; k < G->edgeNum; k++)
    {
        printf("输入边(vi,vj)的顶点序号i,j:\n");
        scanf("%d %d", &i, &j);

        while((c = getchar()) != '\n' && c != EOF);
        
        e = (ArcNode*)malloc(sizeof(ArcNode));
        if (NULL == e)
        {
            return;
        }

        e->adjIndex = j;
        e->nextArc = G->adjList[i].firstArc;
        G->adjList[i].firstArc = e;

        // double direction copy
        e = (ArcNode *)malloc(sizeof(ArcNode));
        if (NULL == e)
        {
            return;
        }
        e->adjIndex = i;
        e->nextArc = G->adjList[j].firstArc;
        G->adjList[j].firstArc = e;
    }
}

int main(int argc, char const *argv[])
{
    ALGraph G;    
    CreateALGraph(&G);

    DFSTraverse(&G);
    return 0;
}

 

运行结果: A F G H E D I C B (与输入顺序有关)
 
邻接矩阵实现:
#include <stdio.h>
#include <malloc.h>

#define MAX_VERTEX_NUM 50 

typedef char vertexType;
typedef int edgeType;

typedef struct
{
    vertexType vexs[MAX_VERTEX_NUM];
    edgeType arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    int vexNum;
    int edgeNum;
}Graph;

int visit[MAX_VERTEX_NUM] = {0};

void CreateALGraph(Graph *G)
{
    int i, j, k;
    int c;

    printf("输入顶点数和边数:\n");
    scanf("%d %d", &G->vexNum, &G->edgeNum);
    setbuf(stdin, NULL);

    for (i = 0; i < G->vexNum; i++)
    {
        printf("输入第%d个顶点信息:\n", i + 1);
        scanf("%c", &G->vexs[i]);

        while((c = getchar()) != '\n' && c != EOF);
    }

    for (i = 0; i < G->vexNum; i++)
    {
        for (j = 0; j < G->vexNum; j++)
        {
            G->arc[i][j] = 0;
        }
    }


    for (k = 0; k < G->edgeNum; k++)
    {
        printf("输入边(vi,vj)的下标i,j:\n");
        scanf("%d %d", &i, &j);

        while((c = getchar()) != '\n' && c != EOF);

        // set a default weight
        G->arc[i][j] = G->arc[j][i] = 1;   
    }
}

void DFS(Graph G, int i)
{
    visit[i] = 1;
    printf("%c ", G.vexs[i]);

    for (int j = 0; j < G.vexNum; j++)
    {
        if (G.arc[i][j] == 1 && !visit[j])
        {
            DFS(G, j);
        }
    }
}

void DFSTraverse(Graph G)
{
    for (int i = 0; i < G.vexNum; i++)
    {
        if (!visit[i])
        {
            DFS(G, i);
        }
    }
}

int main(int argc, char const *argv[])
{
    Graph G;    
    CreateALGraph(&G);

    DFSTraverse(G);
    return 0;
}
运行结果: A B C D E F G H I