前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据结构与算法-图的遍历

数据结构与算法-图的遍历

作者头像
越陌度阡
发布2020-11-26 10:30:17
4810
发布2020-11-26 10:30:17
举报

图的遍历即为从图G中某一顶点v出发,顺序访问各顶点一次。

为克服顶点的重复访问,设立辅助数组visited[],若visited[i]为1,代表顶点已被访问过,若为0,代表顶点i未被访问过。

深度优先搜索法(DFS)

从图G(V,E)中任一顶点Vi开始,首先访问Vi,然后访问Vi的任一未访问过的邻接点Vj,再以Vj为新的出发点继续进行深度优先搜索,直到所有顶点都被访问过。

搜索到达某个顶点时(图中仍有顶点未被访问),如果这个顶点的所有邻接点都被访问过,那么搜索就要回到前一 个被访问过的顶点,再从该顶点的下一未被访问的邻接 点开始深度优先搜索。

深度搜索的顶点的访问序列不是唯一的。

DFS算法分析:

1. 为克服顶点的重复访问,设立一标志向量visited [n];

2. 图可用邻接矩阵或邻接表表示;

3. DFS规则具有递归性,故需用到栈。

DFS算法实现(邻接表):

代码语言:javascript
复制
void Dfs ( Graph g , int v ) {
    ArcNode *p ;
    printf ( "%d",v );
    // 置"已访问"标记
    visited [v] = 1; 
    // 取顶点表中v的边表头指针
    p = g.adjlist[v].firstarc ; 
    // 依次搜索v的邻接点
    while ( p != NULL ) { 
        // v的一个邻接点未被访问
        if ( ! visited[p->adjvex] ){
            // 沿此邻接点出发继续DFS
            Dfs ( g,p->adjvex ); 
        };
        // 取v的下一个邻接点
        p = p->nextarc ; 
    }
}

DFS算法实现(邻接矩阵):

代码语言:javascript
复制
void Dfs ( Graph g , int v ) {
    int j ;
    printf ("%d",v ); 
    // 置"已访问"标记
    visited [v] = 1; 
    // n为顶点数,j为顶点编号
    for (j=0;j<n;j++){ 
        // 顺序访问矩阵的第v行结点
        m=g->arcs[v][j];
        // 如果v与j邻接,且j未被访问
        if(m&&!visited[j]){
            // 递归访问j
            Dfs (g,j) ; 
        }
    }
}

DFS邻接表的实例:

广度优先搜索法(BFS)

从图G(V,E)中某一点Vi出发,首先访问Vi的所有邻接点(W1,W2,…,Wt),然后再顺序访问W1,W2, …,Wt的所有未被访问过的邻接点, 此过程直到所有顶点都被访问过。

BFS算法分析:

1. 为克服顶点的重复访问,设立一标志向量 visited[n];

2. 图可用邻接矩阵或邻接表表示;

3. 顶点的处理次序先进先出,故需用到队列。

BFS算法实现(邻接表):

代码语言:javascript
复制
Bfs(Graph g,int v){ 
    // Q为链队列
    LkQue Q;
    ArcNode *p;
    InitQueue(&Q); 
    printf("%d",v); 
    // 置已访问标志 
    visited[v]=1;
    // 访问过的顶点入队列
    EnQueue(&Q,v); 

    while(!EmptyQueue(Q)){ 
        v=Gethead(&Q);
        // 顶点出队列 
        OutQueue(&Q); 
        // 找到v的第一个邻接点 
        p = g.adjlist[v].firstarc; 
        // 判断邻接点是否存在 
        while(p!=NULL){ 
            // 邻接点存在未被i方问
            if (visited[p->adjvex]){ 
                printf ("%d",p->adjvex); 
                // 置已访问标志 
                visited[p->adjvex]=1; 
                // 邻接点入队列
                EnQueue(&Q,p->adjvex);
            }
            //沿着v的邻接点链表顺序搜索
            p=p->nextarc
        }
    }
}

BFS算法实现(邻接矩阵):

代码语言:javascript
复制
Bfs (Graph g, int v){
    // Q为链队列
    LkQue Q; 
    int j;
    InitQueue(&Q);
    // v为访问的起始结点
    printf("%d",v); 
    // 访问过的标志
    visited[v]=1; 
    EnQueue(&Q,v);
    // 判队列是否为空
    while ( !EmptyQueue(Q)) { 
        v=Gethead(&Q);
        // 出队列
        OutQueue(&Q); 
        // n为顶点数,变化j依次尝试v的可能邻接点
        for (j=0;j<n;j++) { 
            m=g->arcs[v][j];
            // 判断是否邻接点,且未被访问
            if (m && !visited[j]) { 
                printf("%d",j);
                // 置被访问标志
                visited[j]=1; 
                // 邻接点入队列
                EnQueue(&Q,j);
            }
        }
    }
}

BFS邻接表的实例:

求图的连通分量

1. 判断图的连通性

对图G调用一次DFS或BFS,得到一顶点集合,然后将之与V(G)比较,若两集合相等,则图G是连通图,否则就说明有未访问过的顶点,因此图不连通。

2. 求图的连通分量

从无向图的每个连通分量的一个顶点出发遍历, 则可求得无向图的所有连通分量。

算法实现:

代码语言:javascript
复制
int visited[vnum];
Count_Component(Graph g){
    int count ,v;
    // 初始化visted数组
    for(v=0;v<g.exnum;v++){
        visted[v]=0;
    };
    count = 0;
    for(v=0;v<g.vexnum;v++){
        if(!visited[v]){
            count++;
            printf("连通分量%d包含以下顶点:",count);
            Dfs(g,v);
            printf("\n");
        };
    };
    printf("共有%d个连通分量\n",count);
}

连通分量计算实例:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/06/02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 深度优先搜索法(DFS)
  • 广度优先搜索法(BFS)
  • 求图的连通分量
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档