图的遍历算法

1、深度优先遍历

*******、遍历过程(和树的先序遍历思想一样)

深度优先搜素(DFS)遍历类似于树的先序遍历,是树的先序遍历的推广!
(1)、从图中某个顶点v出发,访问v
(2)、找出刚访问过顶点的第一个未被访问的邻接点,访问该顶点。以该顶点为新顶点,重复此步骤,直到刚访问过的顶点没有未被访问的邻接点为止!
(3)、返回前一个访问过的且仍有未被访问的邻接点的顶点,找出该顶点的下一个未被访问的邻接点,访问该顶点!(沿着原路返回执行(3))
(4)、重复(2)(3)步骤,直到所有的顶点都被访问过,搜索停止!

*******、算法步骤

(1)、从某个顶点v出发,访问v,并修改访问信息为true
(2)、依次检查v的所有邻接点w,如果visited[v] 的值为false,再从w出发进行递归遍历,直到图中所有的顶点都被访问!

*******、算法实现

//深度优先遍历非连通图
void DFSTraverse(Graph G){
      //对非连通图G做深度优先遍历
      for(int v = 0; v < G.vexnum: ++V){
           visited[v] = false;                     //访问数组初始化
      }
      for(int v = 0; v < G.vexnum: ++V){           //循环调用算法DFS
           if (!visited[v]) DFS(G,v);              //对尚未访问的顶点调用DFS算法
      }
}
void DFS(Graph G,int v){                           //从第v个顶点出发递归第深度优先遍历图G
     cout<<v;                                      //打印当前访问的点
     visited[v] = true;                            //修改访问变量
     for(int w = FisrstAdjvex(G,V); w >= 0; w =  NextAdjvex(G,v,w){
     //依次检查v的所有邻接点,FisrstAdjvex(G,V)表示的是v的第一个邻接点
     //NextAdjvex(G,v,w)表示v相对于w的下一个邻接点,w >= 0表示存在邻接点
           if (!visited[w]) DFS(G,w);              //对尚未访问的顶点调用DFS算法
     }                   
}

*******、算法分析

(1)、首先深度优先遍历结果是不唯一的,而且是使用栈的思想解决问题的!实际是使用递归来调用系统提供的栈来解决问题的!
(2)、分析上述算法,在遍历图的时候,对图中的每个顶点至多调用依次DFS函数,因为一旦某个顶点被已经访问过,就不再从他出发进行搜索。因此,遍历图的过程实质上是对每个顶点查找其邻接点的过程,所消耗的时间取决于算法所采用的存储结构!当采用邻接矩阵表示图的时候,查找其每个顶点的邻接点的时间复杂度为o(n*n),其中n是图中的顶点数。而当以邻接表做图的存储结构的时候,查找邻接点的时间复杂度为o(e),其中e为图的边数。因此,当采用邻接表做存储结构的时候,深度优先遍历搜索的时间复杂度是o(n+e)(n个顶点存储在数组中)

2、广度优先遍历

*******、遍历过程(和树的层次遍历思想是一样的)

广度优先遍历算法类似于树的层次遍历算法!
(1)、从图中某个顶点出发,访问v
(2)、依次访问v的各个未曾访问到的邻接点
(3)、分别从这些邻接点出发依次访问他们的邻接点,并且使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问。重复步骤(3),直到图中所有已被访问的顶点的邻接点都被访问到!

*******、算法步骤

(1)、从某个顶点v出发,访问v,并修改访问信息为true,然后将v进队
(2)、只要队列不空,则重复执行以下操作:
*******、队头顶点u出队
*******、依次检查v的所有邻接点w,如果visited[v] 的值为false,则访问w,并置访问信息为true,然后将w进队!

*******、算法实现

//广度优先遍历非连通图
void BFSTraverse(Graph G){
      //对非连通图G做深度优先遍历
      for(int v = 0; v < G.vexnum: ++V){
           visited[v] = false;                     //访问数组初始化
      }
      for(int v = 0; v < G.vexnum: ++V){           //循环调用算法BFS
           if (!visited[v]) BFS(G,v);              //对尚未访问的顶点调用BFS算法
      }
}
void BFS(Graph G,int v){                           //从第v个顶点出发广度优先遍历图G
     cout<<v;                                      //打印当前访问的点
     visited[v] = true;                            //修改访问变量
     InitQueue(Q);                                 //初始化辅助存储空间
     Enqueue(Q,v);                                 //v进队
     while(!QueueEmpty(Q){                         //队列非空
           Dequeue(Q,u);                           //队头元素出队并置为u
           for(int w = FisrstAdjvex(G,u); w >= 0; w =  NextAdjvex(G,u,w){   //找队头元素的各个邻接点
            //依次检查u的所有邻接点,FisrstAdjvex(G,u)表示的是v的第一个邻接点
            //NextAdjvex(G,u,w)表示u相对于w的下一个邻接点,w >= 0表示存在邻接点
                   if (!visited[w]) 
                   {
                         cout<<w;
                         visited[w] = true;                //访问w,并修改访问标志
                         Enqueue(Q,w);                     //w进队
                   }
          }             

     }
     
}

*******、算法分析

广度优先遍历可以看成是树的层次遍历,使用队列的思想!分析上面的算法,每个顶点最多进一次队列。遍历图的实质上是通过边找邻接点的过程,因此广度优先搜索遍历图的时间复杂度和深度优先搜索遍历相同!所以使用邻接矩阵存储的时候,时间复杂度为o(n*n),使用邻接表实现存储结构的时候,时间复杂度为o(n+e)。两个唯一不同的是,两种方法使用的实现方法不同,一个是使用递归(背后调用的是系统栈),一个是使用队列,故两种遍历方法的不同之处仅仅在于对顶点访问的顺序不同而已!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Q渡劫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值