深度优先搜索 && 广度优先搜索

类比二叉树先序遍历与图深度优先搜索

在引入图的深度优先搜索之前,为了更加容易理解.先考究一种特殊的图---二叉树的深度优先搜索算法---即二叉树的递归遍历方法.

二叉树的前序遍历算法:

    void TreeWalk(node* root)
    {
        if(root)
        {
            visit(root);
            TreeWalk(root->left);
            TreeWalk(root->right);
        }
    }  

对于二叉树来说,步骤如下:

1.如果root不为空,先访问root,

2再递归下降地访问root->left和root->right.

在二叉树中,与root邻接的结点只有left and right.所以,每次只需要递归下降访问这两个节点即可.

对于图来说,可以类比二叉树(特殊情况),总结出一般规律:

1先选定任意一个点vex做为生成树的根结点.访问该根点,

2再递归下降地访问与vex邻接的而且未被访问过的所有结点.

在图中,与vex邻接的结点是不像二叉树一样只有left 和 right,因为是不确定的,因此需要循环地查找判断哪些点邻接并且尚未被访问过.

伪代码:

    void DFS(Graph& g,int vex)
    {
        Visit vex and Mark vex is visited;
        for w=FirstAdjacencyVertex to LastAdjacencyVertex(which is not visited before)
            DFS(g,w)
    }  
//深度优先算法,可以形成一棵树
void DFS(Graph& g,int vex)
{
    cout<<vex<<' ';
    visited[vex]=true;//is visited
    int w=FirstAdjVertex(g,vex);
    while(w>0)
    {
        DFS(g,w);
        w=NextAdjVertex(g,vex,w);
    }
}  

其中,FirstAdjVertex(g,vex)可以返回vex的第一个未被访问的邻接结点w.NextAdjVertex(g,vex,w)可以返回vex的下一个未被访问的邻接结点,在编号上在w之后.(小编号结点优先原则).

    //找第一个未被访问过的邻接结点,找不到返回0
    int FirstAdjVertex(Graph& g,int vex)
    {
        for(int i=1;i<=g.vnum;++i)//从点1开始找与vex邻接的第一个结点
        {
            if(g.edge[vex][i]==1 && !visited[i])
                return i;
        }
        return 0;
    }
    //找下一个未被访问过的邻接结点
    int NextAdjVertex(Graph& g,int vex,int w)
    {
        for(int i=w;i<=g.vnum;++i)//从w开始,找下一个未被访问过的邻接结点
        {
            if(g.edge[vex][i]==1 && !visited[i])//若i与vex邻接且i未访问过,下一次遍历,就从这个点往下.
                return i;
        }
        return 0;//点都从1开始,返回0则所以点已访问过
    }  

对于无向连通图或者强有向强连通图,可以调用DFS形成一棵深度优先搜索树.但是,对于非连通图或者非强连通图.需要在生成一棵树之后,继续寻找是否还存在未被访问到的点,在这些点上继续调用DFS,最终形成森林.

    void DFS_traver(Graph& g)
    {
        for(int i=1;i<=g.vnum;++i)
        {
            if(!visited[i])//如果i结点未被访问过,形成森林
                DFS(g,i);
        }
    }  

图的广度优先遍历BFS算法是一个分层搜索的过程,和树的层序遍历算法类同,它也需要一个队列以保持遍历过的顶点顺序,以便按出队的顺序再去访问这些顶点的邻接顶点。

1.连通图的广度优先遍历算法思想。

(1)顶点v入队列。

(2)当队列非空时则继续执行,否则算法结束。

(3)出队列取得队头顶点v;访问顶点v并标记顶点v已被访问。

(4)查找顶点v的第一个邻接顶点col。

(5)若v的邻接顶点col未被访问过的,则col入队列。

(6)继续查找顶点v的另一个新的邻接顶点col,转到步骤(5)。直到顶点v的所有未被访问过的邻接点处理完。转到步骤(2)。

int visited[8];
    void BFS(int edge[][8],int vex)
    {
        queue<int> q;
        //visited[vex] = 1;                                //标记已被访问过
        q.push(vex);                                        //初始化队列  

        while(!q.empty())
        {
            vex=q.front();
            q.pop();                                        //取出队头数据
            if(!visited[vex])
            {
            	cout<<vex<<' ';
            	visited[vex] = 1;                    //标记已被访问过
            }

            for ( int j=0; j<8; ++j )
            {
                if(edge[vex][j] == 1 && !visited[j] )        //邻接未被访问过的结点入队
                {
                    q.push(j);
                }
            }
        }
    }
    void BFS_traver(int g[][8])
    {
    	int i;
    	for(i=0;i<8;i++)
    		visited[i]=0;
        for(i=0;i<8;++i)
        {
            if(!visited[i])
			{
			  BFS(g,i);                             //如果i结点未被访问过,形成森林
            }
        }
    } 

这里使用了一个有八个顶点的图

时间: 2025-01-15 03:56:01

深度优先搜索 && 广度优先搜索的相关文章

无向图的深度优先与广度优先搜索代码实现

图采用了邻接表的形式储存. 带不带权都无所谓的 深度优先搜索 Depth First Search 道理和树的先序遍历差不多,把将要访问的点入栈,然后从栈里取点进行访问. 由于这只是类中的一个成员函数,有些被调用的函数的具体代码将会在文章最后补上 ,但是函数功能看注释就好了 1 //深度优先 2 void GraphAdjacencyListWeight::DFSAdvanced(int StartVertex) { 3 int *visited = new int[VertexNumber];

图的遍历(深度优先与广度优先搜索两种方案)

1.图的遍历--深度优先搜索 import java.util.Scanner ; public class Map{ static int n ; static int m ; static int[] book ; static int[][] e ; public static void mapDfs(int cur){ //深度优先搜索思想核心: System.out.print(cur + " ") ; for (int i=1;i<=n;i++) { if (e[cu

图论 深度优先搜索 广度优先搜索的非递归实现

深度优先遍历 1.深度优先遍历的递归定义 假设给定图G的初态是所有顶点均未曾访问过.在G中任选一顶点v为初始出发点(源点),则深度优先遍历可定义如下:首先访问出发点v,并将其标记为已访问过:然后依次从v出发搜索v的每个邻接点w.若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止.若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止. 图的深度优先遍历类似于树的

【图论】广度优先搜索和深度优先搜索

写在最前面的 这篇文章并没有非常详细的算法证明过程.导论里面有非常详细的证明过程.本文只阐述“广度优先和深度优先搜索的思路以及一些简单应用”. 两种图的遍历算法在其他图的算法当中都有应用,并且是基本的图论算法. 广度优先搜索 广度优先搜索(BFS),可以被形象的描述为“浅尝辄止”,具体一点就是每个顶点只访问它的邻接节点(如果它的邻接节点没有被访问)并且记录这个邻接节点,当访问完它的邻接节点之后就结束这个顶点的访问. 广度优先用到了“先进先出”队列,通过这个队列来存储第一次发现的节点,以便下一次的

js图的数据结构处理----邻链表,广度优先搜索,最小路径

//邻居连表 //先加入各顶点,然后加入边 //队列 var Queue = (function(){ var item = new WeakMap(); class Queue{ constructor(){ item.set(this,[]); } enqueue(ele){ var ls = item.get(this); ls.push(ele); } dequeue(){ var ls = item.get(this); return ls.shift(); } size(){ var

深度和广度优先搜索

我们知道,算法是作用于具体数据结构之上的,深度优先搜索算法和广度优先搜索算法都是基于“图”这种数据结构的.这是因为,图这种数据结构的表达能力很强,大部分涉及搜索的场景都可以抽象成“图”. 无向图的代码实现 public class Graph { // 无向图 private int v; // 顶点的个数 private LinkedList<Integer> adj[]; // 邻接表 public Graph(int v) { this.v = v; adj = new LinkedLi

【算法导论】--C++实现广度优先搜索bfs

一.题目 根据上次随机生成的100个顶点的无向图和有向图,对其进行广度优先搜索. 二.理解广度优先搜索 广度优先搜索可以将其想象成水滴落入水面溅起了的一圈一圈的涟漪,是由一个起始点开始一圈一圈进行扩散搜索的. [课上老师是这样说的,大家想象一下,发现其实非常形象] 广度优先搜索总是从一个起始点出发,首先扩散这个点周围所有的邻居,然后邻居在去扩散邻居的邻居(*^-^*)...然后一直到最后将整张图都扩散完. 三.代码实现 对于第一次随机生成100个顶点的图进行了细节的修改,将每个顶点的类型改为了自

广度优先搜索(bfs)

学了将近半年的信息了,昨天猛地间发现我好像不会搜索.... 这就意味着我在noip的时候连暴力都不会打...为了避免这种事情的发生,我决定一定要好好学搜索.. 好了,废话不多说了,下面开始我们的正式话题:广度优先搜索 1.前言 广度优先搜索其实是一种用来遍历连通图的一种算法,它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域,故得名.                       貌似有的东西就真的跟徐大佬说的一样:说不清楚,只能靠自己去做题才能真正理解. 所以,如果我说的你不是很明白

【算法】广度优先搜索

广度优先搜索(breadth first search) 图 最短路径问题(shorterst-path problem) 解决最短路径问题的算法被称为广度优先搜索. 最短路径问题解决步骤 (1) 使用图来建立问题模型. (2) 使用广度优先搜索解决问题. 图的定义 图模拟一组连接. 图由节点(node)和边(edge)组成.一个节点可能与众多节点直接相连,这些节点被称为邻居.图用于模拟不同的东西是如何相连的. 广度优先搜索 广度优先搜索是一种用于图的查找算法,可帮助回答两类问题. 第一类问题: