zoukankan      html  css  js  c++  java
  • 【数据结构】图的深度优先搜索

      图的深度优先搜索类似于树的深度优先搜索。不同的是,图中可能包括循环,即我们有可能重复访问节点。为了避免访问已经访问过的节点,我们要使用一个布尔变量的数组。

      例如,在下图中,我们从节点2开始访问。当访问到节点0,我们寻找它的所有紧接节点。节点2也属于节点0的邻接节点。如果我们没有标记访问的节点,那么节点2 将会被重复访问,这样的话整个算法过程就不会停下来了。下图的深度优先搜索是2,0,1,3

      这种搜索算法所遵循的搜索策略是尽可能“深”地搜索一个图。它的基本思想如下:首先访问图中某一起始顶点v,然后由v出发,访问与v邻接且未被访问的任一顶点w1,再访问与w1邻接且未被访问的任一顶点w2,......重复上述过程。当不能再继续向下访问时,一次退回到最近被访问的顶点,若它还有邻接顶点未被访问过,则从该点开始继续上述搜索过程,直到图中所有顶点均被访问过为止。

      举个例子:

      

      上图一幅无向图。我们从A点开始遍历,并假设左边的节点先被访问到。那么访问顺序是A,搜索A所有可访问的邻接节点并选择B,然后访问B,搜索B所有可访问的邻接节点并选择D,然后访问D,搜索D的所有可访问的邻接节点。由于D只有一个邻接节点B,而B已经被访问过。所以回退到D的上级B(注意,不是访问B,仅仅是回到上级)。然后再搜索B的所有可访问的邻接节点,AD已经被访问过,所以访问F。这个过程一直持续直到访问过所有的节点。

      选择可访问邻接节点的时候,可以使用我们自己定义的顺序。比如访问A的邻接节点的时候,可以先访问B,也可以先访问E。可根据需求灵活调整。

    下述代码是深度优先搜索的C++版本,有递归和迭代版本。图的实现使用邻接链表表示。STL的list被用来存储邻接节点。

    #include<list>
    #include<iostream>
    using namespace std;
    
    
    class Graph {
     private:
         int V;
         list<int>* adj;
         void DfsUtil(int v, bool visited[]);
    
     public:
         Graph(int n);    //No of vertices
         ~Graph();    //Pointer to an array containing adjacency lists
         void addEdge(int v, int w);    //function to add an edge to graph
         void Dfs(int s);    //Dfs traversal of the vertices reachable from v
         void DfsIter(int s);
    };
    
    Graph::Graph(int v) {
        V = v;
        adj = new list<int>[V];
    }
    
    Graph::~Graph() {
        delete []adj;
        adj = NULL;
    }
    
    void Graph::addEdge(int v, int w) {
        adj[v].push_back(w);    //Add w to v's list
    }
    
    void Graph::Dfs(int s) {
        bool* visited = new bool[V];
        for (int i = 0; i < V; i++)
            visited[V] = false;
    
        DfsUtil(s, visited);
    }
    
    void Graph::DfsUtil(int v, bool visited[]) {
        //Mark the current node as the visited and print it
        visited[v] = true;
        cout<<v<<" ";
    
        //Recur for all vertices adjacent to this vertex
        list<int>::iterator i;
        for (i = adj[v].begin(); i != adj[v].end(); i++)
            if (!visited[*i])
                DfsUtil(*i, visited);
    }
    
    void Graph::DfsIter(int v) {
        bool*  visited = new bool[V];
        for (int i = 0; i < V; i++)
            visited[i] = false;
    
       list<int> stack;
       
       stack.push_back(v);
    
       list<int>::iterator i;
       while (!stack.empty()) {
        v = stack.back();
        cout<<v<<" ";
        stack.pop_back();
        visited[v] = true;
    
        for(i = adj[v].begin(); i != adj[v].end(); i++)
            if (!visited[*i])
                stack.push_back(*i);
       } 
    
       delete []visited;
    }
    
    
    int main()
    {
        // Create a graph given in the above diagram
        Graph g(4);
        g.addEdge(0, 1);
        g.addEdge(0, 2);
        g.addEdge(1, 2);
        g.addEdge(2, 0);
        g.addEdge(2, 3);
        g.addEdge(3, 3);
     
        cout << "Following is Depth First Traversal (starting from vertex 2) 
    ";
        g.DfsIter(2);
     
        return 0;
    }

    输出:

    Following is Depth First Traversal (starting from vertex 2)
    2 0 1 3

    参考资料:

      1. http://www.geeksforgeeks.org/depth-first-traversal-for-a-graph/

  • 相关阅读:
    OSX安装nginx和rtmp模块(rtmp直播服务器搭建)
    用runtime来重写Coder和deCode方法 归档解档的时候使用
    Homebrew安装卸载
    Cannot create a new pixel buffer adaptor with an asset writer input that has already started writing'
    OSX下面用ffmpeg抓取桌面以及摄像头推流进行直播
    让nginx支持HLS
    iOS 字典转json字符串
    iOS 七牛多张图片上传
    iOS9UICollectionView自定义布局modifying attributes returned by UICollectionViewFlowLayout without copying them
    Xcode6 iOS7模拟器和Xcode7 iOS8模拟器离线下载
  • 原文地址:https://www.cnblogs.com/vincently/p/4769617.html
Copyright © 2011-2022 走看看