图的遍历

本文探讨了图的遍历方法,包括广度优先遍历(BFS)和深度优先遍历(DFS)。无论是使用邻接矩阵还是邻接表,这两种遍历方式在实现上都有相似之处,BFS利用队列进行节点的顺序处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

图的遍历主要分为两种形式:广度优先遍历(BFS) 和深度优先遍历(DFS)。

对于图的遍历来说,不管是采用的邻接矩阵的方式,还是采用的邻接表的形式,其实现都是类似的,甚至可以说是一样的。

广度遍历

广度遍历利用了队列的特点,结点顺序的放入队列中,然后再出来。

对于采用邻接表还是邻接矩阵,两者实际上是非常类似的:

void BFSTraverse(MGraph G,Status(*Visit)(VertexType))
{ /* 初始条件: 图G存在,Visit是顶点的应用函数。*/
  /* 操作结果: 从第1个顶点起,按广度优先非递归遍历图G,并对每个顶点调用函数 */
  /*           Visit一次且仅一次。一旦Visit()失败,则操作失败。 */
  /*           使用辅助队列Q和访问标志数组visited */
  int v,u,w;
  VertexType w1,u1;
  LinkQueue Q;
  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 */
        strcpy(u1,*GetVex(G,u));
        for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,u1,strcpy(w1,*GetVex(G,w))))  //对于采用邻接表还是邻接矩阵,主要的不同还是在于这里first,next  的实现的不同。
          if(!visited[w]) /* w为u的尚未访问的邻接顶点的序号 */
          {
            visited[w]=TRUE;
            Visit(G.vexs[w]);
            EnQueue(&Q,w);
          }
      }
    }
printf("\n");
}


 

当时邻接表时,是:

(最后还有一个p=p->next)

如果是邻接矩阵,则是:

 

深度遍历

深度遍历完全可以理解为一个递归的过程。

 

void DFSTraverse(MGraph G,Status(*Visit)(VertexType))
{ /* 初始条件: 图G存在,Visit是顶点的应用函数。*/
  /* 操作结果: 从第1个顶点起,深度优先遍历图G,并对每个顶点调用函数Visit */
  /*           一次且仅一次。一旦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); /* 对尚未访问的顶点调用DFS */
  printf("\n");
}

无论是邻接表还是邻接矩阵,这两者都是一样的。不同的是在DFS的部分。

void DFS(MGraph G,int v)
{ /* 从第v个顶点出发递归地深度优先遍历图G。*/
  VertexType w1,v1;
  int w;
  visited[v]=TRUE; /* 设置访问标志为TRUE(已访问) */
  VisitFunc(G.vexs[v]); /* 访问第v个顶点 */
  strcpy(v1,*GetVex(G,v));
  for(w=FirstAdjVex(G,v1);w>=0;w=NextAdjVex(G,v1,strcpy(w1,*GetVex(G,w))))  //不同的地方就在这里
    if(!visited[w])
      DFS(G,w); /* 对v的尚未访问的序号为w的邻接顶点递归调用DFS */
}


对于不同的地方,还是在广度遍历中提到的部分。但是在这里,不同的地方还是完全一样的。跟上面的图完全一样。

 

这两种遍历算法在时间复杂度上是一样的。但是采用不同的存储结构所耗费的是不同的: 采用邻接矩阵,那么会因为搜索每个结点,那么对于需要n个顶点,e条边的图来说,需要O(n2),但是采用邻接表只需要O(n+e).

对于这两种遍历方法哪种会比较合适,这需要看情况了。如在大话数据结构总所说的:




                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值