SlideShare a Scribd company logo
1 of 4
Download to read offline
图的遍历及连通性问题


一、深度优先收索 Depth-First-Search(DFS)
//教材上面算法,这个最重要。后面的具体实现了解。
//               ,
Boolean visited[MAX];                             // 访问标志数组
Status (* VisitFunc))(int v); // 函数指针变量
void DFSTraverse(Graph G, Status(* Visit)(int v))
                                                                                // 对图
G 作深度优先遍历
{VisitFunc = Visit;
                               //               VisitFunc,使 DFS 不必设函数指针参数
                               //使用全局变量 VisitFunc
     for(v=0; v<G.vexnum; ++v) visited[v] = FALSE ;
// 访问标志数组初始化
 for(v=0; v<G.vexnum; ++v )
     if(!Visited[v]) DFS (G,v );    //
                                    //对尚未访问的顶点调用 DFS
}
//从第 v 个顶点出发递归地深度优先遍历图 G
//
void DFS(Graph G, int v)
{visited[v]=TRUE;
  VistFunc(v);                          //访问第 v 个顶点
                                        //
  for(w=FirstAdjVex(G,v);w;
                                               w=NextAdjVex(G,v,w))
   if(!visted[w]) DFS(G,w);
                                 // v 的尚未访问的邻接顶点 w 递归调用 DFS
                                 //对
}


//邻接矩阵作为作为存储结构
Boolean visited[MAX_VERTEX_NUM]; /* 访问标志数组(全局量) */
 void(*VisitFunc)(VertexType); /* 函数变量 */
 void DFS(MGraph G,int v)
 { /* 从第 v 个顶点出发递归地深度优先遍历图 G。算法 7.5 */
    int w;
     visited[v]=TRUE; /* 设置访问标志为 TRUE(已访问) */
     VisitFunc(G.vexs[v]); /* 访问第 v 个顶点 */
     for(w=FirstAdjVex(G,G.vexs[v]);w>=0;w=NextAdjVex(G,G.vexs[v],G.vexs[w]))
        if(!visited[w])
            DFS(G,w); /* 对 v 的尚未访问的序号为 w 的邻接顶点递归调用 DFS */
 }

 void DFSTraverse(MGraph G,void(*Visit)(VertexType))

        1
{ /* 初始条件:图 G 存在,Visit 是顶点的应用函数。算法 7.4 */
   /* 操作结果:从第 1 个顶点起,深度优先遍历图 G,并对每个顶点调用函数 Visit 一次且
仅一次 */
   int v;
        VisitFunc=Visit; /* 使用全局变量 VisitFunc,使 DFS 不必设函数指针参数 */
        for(v=0;v<G.vexnum;v++)
           visited[v]=FALSE; /* 访问标志数组初始化(未被访问) */
        for(v=0;v<G.vexnum;v++)
           if(!visited[v])
              DFS(G,v); /* 对尚未访问的顶点 v 调用 DFS */
}


//邻接表作为存储结构
Boolean visited[MAX_VERTEX_NUM]; /* 访问标志数组(全局量) */
 void(*VisitFunc)(char* v); /* 函数变量(全局量) */
 void DFS(ALGraph G,int v)
    { /* 从第 v 个顶点出发递归地深度优先遍历图 G。算法 7.5 */
       int w;
    visited[v]=TRUE; /* 设置访问标志为 TRUE(已访问) */
    VisitFunc(G.vertices[v].data); /* 访问第 v 个顶点 */
for(w=FirstAdjVex(G,G.vertices[v].data);w>=0;w=NextAdjVex(G,G.vertices[v].data,G.vertices[w].d
ata))
       if(!visited[w])
              DFS(G,w); /* 对 v 的尚未访问的邻接点 w 递归调用 DFS */
    }

    void DFSTraverse(ALGraph G,void(*Visit)(char*))
    { /* 对图 G 作深度优先遍历。算法 7.4 */
       int v;
        VisitFunc=Visit; /* 使用全局变量 VisitFunc,使 DFS 不必设函数指针参数 */
        for(v=0;v<G.vexnum;v++)
           visited[v]=FALSE; /* 访问标志数组初始化 */
        for(v=0;v<G.vexnum;v++)
           if(!visited[v])
              DFS(G,v); /* 对尚未访问的顶点调用 DFS */
}
二、广度优先搜索(Breadth_First Search
                     Breadth_First Search)
//教材上面算法,这个最重要。后面的具体实现了解。
//               ,
void BFSTraverse(Graph G,Status(* Visit)(int v))
{ // 按广度优先非递归遍历图 G。使用辅助队列 Q 和访问标志数组 visited              visited。
 for(v=0; v<G.vexnum; ++v ) visited[v] = FALSE;
 InitQueue(Q);                                   // 置空的辅助队列 Q
 for (v=0; v<G.vexnum; ++v )

          2
if (!visited[v])                                       // v 尚未访问
 {EnQueue(Q, v);                         // v 入队列
     while (!QueueEmpty(Q))
     {DeQueue(Q, u);                            // 队头元素出队并置为 u
      visited[u] = TRUE; Visit(u);                  // 访问 u
      for(w=FirtAdjVex(G,u);w;w=NextAdjVex(G,u,w))
          if(!visited[w]) EnQueue(Q,w);
                                                         // u 的尚未访问的邻接顶点 w
入队列 Q
      }//while
   }// if
}// BFSTraverse
//邻接矩阵作为存储结构
void BFSTraverse(MGraph G,void(*Visit)(VertexType))
{ /* 初始条件:图 G 存在,Visit 是顶点的应用函数。算法 7.6 */
   /* 操作结果:   从第 1 个顶点起,按广度优先非递归遍历图 G,并对每个顶点调用函数 Visit
一次且仅一次 */
   int v,u,w;
    LinkQueue Q; /* 使用辅助队列 Q 和访问标志数组 visited */
    for(v=0;v<G.vexnum;v++)
       visited[v]=FALSE; /* 置初值 */
    InitQueue(&Q); /* 置空的辅助队列 Q */
    for(v=0;v<G.vexnum;v++)
      if(!visited[v]) /* v 尚未访问 */
      {
          visited[v]=TRUE; /* 设置访问标志为 TRUE(已访问) */
          Visit(G.vexs[v]);
          EnQueue(&Q,v); /* v 入队列 */
          while(!QueueEmpty(Q)) /* 队列不空 */
          {
              DeQueue(&Q,&u); /* 队头元素出队并置为 u */
              for(w=FirstAdjVex(G,G.vexs[u]);w>=0;w=NextAdjVex(G,G.vexs[u],G.vexs[w]))
                if(!visited[w]) /* w 为 u 的尚未访问的邻接顶点的序号 */
                {
                    visited[w]=TRUE;
                    Visit(G.vexs[w]);
                    EnQueue(&Q,w);
                }
          }
      }
}
//邻接表作为存储结构
void BFSTraverse(ALGraph G,void(*Visit)(char*))

      3
{/*按广度优先非递归遍历图 G。使用辅助队列 Q 和访问标志数组 visited。算法 7.6 */
    int v,u,w;
    LinkQueue Q;
    for(v=0;v<G.vexnum;++v)
        visited[v]=FALSE; /* 置初值 */
     InitQueue(&Q); /* 置空的辅助队列 Q */
     for(v=0;v<G.vexnum;v++) /* 如果是连通图,只 v=0 就遍历全图 */
        if(!visited[v]) /* v 尚未访问 */
        {
            visited[v]=TRUE;
            Visit(G.vertices[v].data);
            EnQueue(&Q,v); /* v 入队列 */
            while(!QueueEmpty(Q)) /* 队列不空 */
            {
           DeQueue(&Q,&u); /* 队头元素出队并置为 u */
for(w=FirstAdjVex(G,G.vertices[u].data);w>=0;w=NextAdjVex(G,G.vertices[u].data,G.vertices[w].d
ata))
                if(!visited[w]) /* w 为 u 的尚未访问的邻接顶点 */
                {
                    visited[w]=TRUE;
                    Visit(G.vertices[w].data);
                     EnQueue(&Q,w); /* w 入队 */
                }
            }
        }
     printf("n");
 }
三、无向图的连通分量和生成树
应该会画就行了吧,对算法应该没有要求的。
1.连通分量
  无向图的极大连通子图。即子图中不能再增加一个顶点,已有顶点的边均包含在内。
  无向图的连通分量的产生——多次调用 DFS
2.生成树  一个连通图的生成树是一个极小连通子图,且含有图中全部顶点
3.无向图的生成树
  对一个连通图 G,从图中任意一个顶点出发遍历图时,把 E 分为 E1 和 E2,E1 为遍历过程
中经过的边的集合,E2 为剩余边的集合,则 E1 与 V 构成 G 的极小连通图,即连通图的一棵
生成树
  若遍历为 DFS,则称为深度优先生成树
  若遍历为 BFS,则称为广度优先生成树
对于非连通图,每个连通分量中的顶点集合,加上遍历时经过的边,构成了非连通图的生成
森林。




        4

More Related Content

Viewers also liked

数据结构复习笔记 静态链表
数据结构复习笔记 静态链表数据结构复习笔记 静态链表
数据结构复习笔记 静态链表mengyingchina
 
数据结构复习笔记 拓扑排序Topological+sort
数据结构复习笔记 拓扑排序Topological+sort数据结构复习笔记 拓扑排序Topological+sort
数据结构复习笔记 拓扑排序Topological+sortmengyingchina
 
哈佛幸福课[升级版]
哈佛幸福课[升级版]哈佛幸福课[升级版]
哈佛幸福课[升级版]mengyingchina
 
Microlivestock and livelihood security in Hilly regions of India
Microlivestock and livelihood security in Hilly regions of IndiaMicrolivestock and livelihood security in Hilly regions of India
Microlivestock and livelihood security in Hilly regions of IndiaDr Devesh Thakur
 
Quiz feb 2013 vet palampur h.p.
Quiz feb 2013 vet palampur h.p.Quiz feb 2013 vet palampur h.p.
Quiz feb 2013 vet palampur h.p.Dr Devesh Thakur
 
Disaster Preparedness Guide
Disaster Preparedness GuideDisaster Preparedness Guide
Disaster Preparedness Guidecmgreo
 

Viewers also liked (8)

数据结构复习笔记 静态链表
数据结构复习笔记 静态链表数据结构复习笔记 静态链表
数据结构复习笔记 静态链表
 
数据结构复习笔记 拓扑排序Topological+sort
数据结构复习笔记 拓扑排序Topological+sort数据结构复习笔记 拓扑排序Topological+sort
数据结构复习笔记 拓扑排序Topological+sort
 
哈佛幸福课[升级版]
哈佛幸福课[升级版]哈佛幸福课[升级版]
哈佛幸福课[升级版]
 
文献综述
文献综述文献综述
文献综述
 
World vet quiz 2013
World vet quiz 2013World vet quiz 2013
World vet quiz 2013
 
Microlivestock and livelihood security in Hilly regions of India
Microlivestock and livelihood security in Hilly regions of IndiaMicrolivestock and livelihood security in Hilly regions of India
Microlivestock and livelihood security in Hilly regions of India
 
Quiz feb 2013 vet palampur h.p.
Quiz feb 2013 vet palampur h.p.Quiz feb 2013 vet palampur h.p.
Quiz feb 2013 vet palampur h.p.
 
Disaster Preparedness Guide
Disaster Preparedness GuideDisaster Preparedness Guide
Disaster Preparedness Guide
 

数据结构复习笔记 图的遍历及连通性问题

  • 1. 图的遍历及连通性问题 一、深度优先收索 Depth-First-Search(DFS) //教材上面算法,这个最重要。后面的具体实现了解。 // , Boolean visited[MAX]; // 访问标志数组 Status (* VisitFunc))(int v); // 函数指针变量 void DFSTraverse(Graph G, Status(* Visit)(int v)) // 对图 G 作深度优先遍历 {VisitFunc = Visit; // VisitFunc,使 DFS 不必设函数指针参数 //使用全局变量 VisitFunc for(v=0; v<G.vexnum; ++v) visited[v] = FALSE ; // 访问标志数组初始化 for(v=0; v<G.vexnum; ++v ) if(!Visited[v]) DFS (G,v ); // //对尚未访问的顶点调用 DFS } //从第 v 个顶点出发递归地深度优先遍历图 G // void DFS(Graph G, int v) {visited[v]=TRUE; VistFunc(v); //访问第 v 个顶点 // for(w=FirstAdjVex(G,v);w; w=NextAdjVex(G,v,w)) if(!visted[w]) DFS(G,w); // v 的尚未访问的邻接顶点 w 递归调用 DFS //对 } //邻接矩阵作为作为存储结构 Boolean visited[MAX_VERTEX_NUM]; /* 访问标志数组(全局量) */ void(*VisitFunc)(VertexType); /* 函数变量 */ void DFS(MGraph G,int v) { /* 从第 v 个顶点出发递归地深度优先遍历图 G。算法 7.5 */ int w; visited[v]=TRUE; /* 设置访问标志为 TRUE(已访问) */ VisitFunc(G.vexs[v]); /* 访问第 v 个顶点 */ for(w=FirstAdjVex(G,G.vexs[v]);w>=0;w=NextAdjVex(G,G.vexs[v],G.vexs[w])) if(!visited[w]) DFS(G,w); /* 对 v 的尚未访问的序号为 w 的邻接顶点递归调用 DFS */ } void DFSTraverse(MGraph G,void(*Visit)(VertexType)) 1
  • 2. { /* 初始条件:图 G 存在,Visit 是顶点的应用函数。算法 7.4 */ /* 操作结果:从第 1 个顶点起,深度优先遍历图 G,并对每个顶点调用函数 Visit 一次且 仅一次 */ int v; VisitFunc=Visit; /* 使用全局变量 VisitFunc,使 DFS 不必设函数指针参数 */ for(v=0;v<G.vexnum;v++) visited[v]=FALSE; /* 访问标志数组初始化(未被访问) */ for(v=0;v<G.vexnum;v++) if(!visited[v]) DFS(G,v); /* 对尚未访问的顶点 v 调用 DFS */ } //邻接表作为存储结构 Boolean visited[MAX_VERTEX_NUM]; /* 访问标志数组(全局量) */ void(*VisitFunc)(char* v); /* 函数变量(全局量) */ void DFS(ALGraph G,int v) { /* 从第 v 个顶点出发递归地深度优先遍历图 G。算法 7.5 */ int w; visited[v]=TRUE; /* 设置访问标志为 TRUE(已访问) */ VisitFunc(G.vertices[v].data); /* 访问第 v 个顶点 */ for(w=FirstAdjVex(G,G.vertices[v].data);w>=0;w=NextAdjVex(G,G.vertices[v].data,G.vertices[w].d ata)) if(!visited[w]) DFS(G,w); /* 对 v 的尚未访问的邻接点 w 递归调用 DFS */ } void DFSTraverse(ALGraph G,void(*Visit)(char*)) { /* 对图 G 作深度优先遍历。算法 7.4 */ int v; VisitFunc=Visit; /* 使用全局变量 VisitFunc,使 DFS 不必设函数指针参数 */ for(v=0;v<G.vexnum;v++) visited[v]=FALSE; /* 访问标志数组初始化 */ for(v=0;v<G.vexnum;v++) if(!visited[v]) DFS(G,v); /* 对尚未访问的顶点调用 DFS */ } 二、广度优先搜索(Breadth_First Search Breadth_First Search) //教材上面算法,这个最重要。后面的具体实现了解。 // , void BFSTraverse(Graph G,Status(* Visit)(int v)) { // 按广度优先非递归遍历图 G。使用辅助队列 Q 和访问标志数组 visited visited。 for(v=0; v<G.vexnum; ++v ) visited[v] = FALSE; InitQueue(Q); // 置空的辅助队列 Q for (v=0; v<G.vexnum; ++v ) 2
  • 3. if (!visited[v]) // v 尚未访问 {EnQueue(Q, v); // v 入队列 while (!QueueEmpty(Q)) {DeQueue(Q, u); // 队头元素出队并置为 u visited[u] = TRUE; Visit(u); // 访问 u for(w=FirtAdjVex(G,u);w;w=NextAdjVex(G,u,w)) if(!visited[w]) EnQueue(Q,w); // u 的尚未访问的邻接顶点 w 入队列 Q }//while }// if }// BFSTraverse //邻接矩阵作为存储结构 void BFSTraverse(MGraph G,void(*Visit)(VertexType)) { /* 初始条件:图 G 存在,Visit 是顶点的应用函数。算法 7.6 */ /* 操作结果: 从第 1 个顶点起,按广度优先非递归遍历图 G,并对每个顶点调用函数 Visit 一次且仅一次 */ int v,u,w; LinkQueue Q; /* 使用辅助队列 Q 和访问标志数组 visited */ for(v=0;v<G.vexnum;v++) visited[v]=FALSE; /* 置初值 */ InitQueue(&Q); /* 置空的辅助队列 Q */ for(v=0;v<G.vexnum;v++) if(!visited[v]) /* v 尚未访问 */ { visited[v]=TRUE; /* 设置访问标志为 TRUE(已访问) */ Visit(G.vexs[v]); EnQueue(&Q,v); /* v 入队列 */ while(!QueueEmpty(Q)) /* 队列不空 */ { DeQueue(&Q,&u); /* 队头元素出队并置为 u */ for(w=FirstAdjVex(G,G.vexs[u]);w>=0;w=NextAdjVex(G,G.vexs[u],G.vexs[w])) if(!visited[w]) /* w 为 u 的尚未访问的邻接顶点的序号 */ { visited[w]=TRUE; Visit(G.vexs[w]); EnQueue(&Q,w); } } } } //邻接表作为存储结构 void BFSTraverse(ALGraph G,void(*Visit)(char*)) 3
  • 4. {/*按广度优先非递归遍历图 G。使用辅助队列 Q 和访问标志数组 visited。算法 7.6 */ int v,u,w; LinkQueue Q; for(v=0;v<G.vexnum;++v) visited[v]=FALSE; /* 置初值 */ InitQueue(&Q); /* 置空的辅助队列 Q */ for(v=0;v<G.vexnum;v++) /* 如果是连通图,只 v=0 就遍历全图 */ if(!visited[v]) /* v 尚未访问 */ { visited[v]=TRUE; Visit(G.vertices[v].data); EnQueue(&Q,v); /* v 入队列 */ while(!QueueEmpty(Q)) /* 队列不空 */ { DeQueue(&Q,&u); /* 队头元素出队并置为 u */ for(w=FirstAdjVex(G,G.vertices[u].data);w>=0;w=NextAdjVex(G,G.vertices[u].data,G.vertices[w].d ata)) if(!visited[w]) /* w 为 u 的尚未访问的邻接顶点 */ { visited[w]=TRUE; Visit(G.vertices[w].data); EnQueue(&Q,w); /* w 入队 */ } } } printf("n"); } 三、无向图的连通分量和生成树 应该会画就行了吧,对算法应该没有要求的。 1.连通分量 无向图的极大连通子图。即子图中不能再增加一个顶点,已有顶点的边均包含在内。 无向图的连通分量的产生——多次调用 DFS 2.生成树 一个连通图的生成树是一个极小连通子图,且含有图中全部顶点 3.无向图的生成树 对一个连通图 G,从图中任意一个顶点出发遍历图时,把 E 分为 E1 和 E2,E1 为遍历过程 中经过的边的集合,E2 为剩余边的集合,则 E1 与 V 构成 G 的极小连通图,即连通图的一棵 生成树 若遍历为 DFS,则称为深度优先生成树 若遍历为 BFS,则称为广度优先生成树 对于非连通图,每个连通分量中的顶点集合,加上遍历时经过的边,构成了非连通图的生成 森林。 4