圖的遍歷(拓撲、DFS和BFS)

圖的遍歷是指從圖中的某一個頂點出發,按照某種搜索方法沿著圖中的邊對圖中的所有頂點訪問一次且僅訪問一次。注意到樹是一種特殊的圖,所以樹的遍歷實際上也可以看作是一種特殊的圖的遍歷。圖的遍歷主要有兩種算法:廣度優先搜索(Breadth-First-Search)和深度優先搜索(Depth-First-Search)。

深度優先搜索算法所遵循的搜索策略是盡可能“深”地搜索一個圖。它的基本思想就是:首先訪問圖中某一起始頂點v,然后由v出發,訪問與v鄰接且未被訪問的任一頂點w1,再訪問與w1鄰接且未被訪問的任一頂點w2,……重復上述過程。當不能再繼續向下訪問時,依次退回到最近被訪問的頂點,若它還有鄰接頂點未被訪問過,則從該點開始繼續上述搜索過程,直到圖中所有頂點均被訪問過為止。使用遞歸來實現(https://www.zhihu.com/question/20507130

廣度優先搜索類似于二叉樹的層序遍歷,它的基本思想就是:首先訪問起始頂點v,接著由v出發,依次訪問v的各個未訪問過的鄰接頂點w1,w2,…,wi,然后再依次訪問w1,w2,…,wi的所有未被訪問過的鄰接頂點;再從這些訪問過的頂點出發,再訪問它們所有未被訪問過的鄰接頂點……依次類推,直到圖中所有頂點都被訪問過為止。
廣度優先搜索是一種分層的查找過程,每向前走一步可能訪問一批頂點,不像深度優先搜索那樣有往回退的情況,因此它不是一個遞歸的算法。為了實現逐層的訪問,算法必須借助一個輔助隊列,以記錄正在訪問的頂點的下一層頂點。


DFS : 2 0 1 3
BFS : 2 0 3 1

在圖論中,拓撲排序(Topological Sorting)是一個有向無環圖(DAG, Directed Acyclic Graph)的所有頂點的線性序列。且該序列必須滿足下面兩個條件:
1.每個頂點出現且只出現一次。
2.若存在一條從頂點 A 到頂點 B 的路徑,那么在序列中頂點 A 出現在頂點 B 的前面。
有向無環圖(DAG)才有拓撲排序,非DAG圖沒有拓撲排序一說。

它是一個 DAG 圖,那么如何寫出它的拓撲排序呢?這里說一種比較常用的方法:
1.從 DAG 圖中選擇一個 沒有前驅(即入度為0)的頂點并輸出。
2.從圖中刪除該頂點和所有以它為起點的有向邊。
3.重復 1 和 2 直到當前的 DAG 圖為空或當前圖中不存在無前驅的頂點為止。后一種情況說明有向圖中必然存在環。
可以使用在工期排序、大小關系排列、選課時的先修課(即要先修某某課才能學這一門課,先學了C語言再學數據結構這樣)等情況。


拓撲排序

內容來自(http://blog.csdn.net/lisonglisonglisong/article/details/45543451

#include <iostream>
#include <cstdio>
#include <list>
#include <queue>
using namespace std;
class Graph
{
    int V;                       //結點數目
    list<int> *adj;              //鄰接矩陣
    int* inDegree;               //入度數組
    queue<int> q;                //入度為0的隊列
    void BFSUtil(int v, bool visited[]);       //內部接口
    void DFSUtil(int v, bool visited[]);
public:
    Graph(int v);
    ~Graph();
    void addEdge(int v, int w);
    bool topoSort();
    void DFS(int v);            //外部接口
    void BFS(int v);           
};
Graph::Graph(int v)
{
    this->V = v;
    adj = new list<int>[v];
    inDegree = new int[v];
    for(int i = 0; i < v; i++)      //新生成的圖每個節點的入度都為0
       inDegree[i] = 0;
}
Graph::~Graph()
{
    delete [] adj;
    delete [] inDegree;
}
void Graph::addEdge(int v, int w)        //點v w相連接
{
    adj[v].push_back(w);
    inDegree[w]++;
}
bool Graph::topoSort()
{
    for(int i = 0; i < V; i++)
        if(inDegree[i]==0)
            q.push(i);
    int cnt = 0, v;               //cnt統計遍歷節點數目 v記錄此時遍歷節點
    while(!q.empty())
    {
        v = q.front();
        q.pop();
        printf("%d ",v);
        cnt++;
        for(list<int>::iterator i=adj[v].begin(); i!=adj[v].end(); i++)
            if(!(--inDegree[*i]))
                q.push(*i);
    }
    if(cnt == V)
        return true;
    else
        return false;
}
void Graph::BFSUtil(int v, bool visited[])
{
    queue<int> que;
    visited[v] = true;
    que.push(v);
    int node;                   //出隊元素
    while(!que.empty())
    {
        node = que.front();
        printf("%d ",node);
        que.pop();
        for(list<int>::iterator i = adj[node].begin(); i != adj[node].end(); ++i)
            if(!visited[*i])
            {
                visited[*i] = true;
                que.push(*i);
            }
    }
}
void Graph::BFS(int v)
{
    bool *visited = new bool[V];
    for(int i = 0; i < V; i++)
        visited[i] = false;
    BFSUtil(v, visited);
}
void Graph::DFSUtil(int v, bool visited[])
{
    visited[v] = true;
    printf("%d ",v);
    for(list<int>::iterator i = adj[v].begin(); i != adj[v].end(); ++i)
        if(!visited[*i])
        {
            visited[*i] = true;
            DFSUtil(*i, visited);
        }
}
void Graph::DFS(int v)
{
    bool *visited = new bool[V];
    for(int i = 0; i < V; i++)
        visited[i] = false;
    DFSUtil(v, visited);
}
int main()
{
    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);

   // g.topoSort();

    g.BFS(2);
    printf("\n");
    g.DFS(2);

    return 0;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • https://zh.visualgo.net/graphds 淺談圖形結構https://zh.visualgo...
    狼之獨步閱讀 4,222評論 0 0
  • 圖是一種比線性表和樹更復雜的數據結構,在圖中,結點之間的關系是任意的,任意兩個數據元素之間都可能相關。圖是一種多對...
    Alent閱讀 2,342評論 1 22
  • 第一章 緒論 什么是數據結構? 數據結構的定義:數據結構是相互之間存在一種或多種特定關系的數據元素的集合。 第二章...
    SeanCheney閱讀 5,821評論 0 19
  • 本文介紹圖的幾種基本操作:BFS,DFS,求有向圖連通分量的Tarjan算法以及拓撲排序。 圖的表示 一張圖是由若...
    maxkibble閱讀 3,476評論 0 2
  • 1 概述 圖是數據結構中最復雜的形式,也是最燒腦的結構。無數的牛人樂此不疲地鉆研,然而,時至今日,依然有很多問題等...
    CodingTech閱讀 2,390評論 0 8