• 《算法导论》学习总结 — XX.第22章 图的基本算法


    BFS(广搜):

    广搜就是广度优先搜索,根据名字可以知道,是通过广度来遍历图,也就是层次遍历吧。

    在这里以及下面的DFS(深搜),都用到了颜色WHITE,GRAY,BLACK,不过作用不同,具体分别再分析。

    在BFS中,WHITE,GRAY,BLACK这三色是用来记录一个点是否被搜到,以及是否它的邻接点都是灰色。(具体见P324倒数第2段)。

    P326 的图22-3是个经典的图,看了此图基本就知道BFS是干嘛的了。

    在图22-3中,因为他是用字母表示的,我把各点定义为顺时针从标号1开始,于是r点是1号,源点s是2号。

    这是我写的具体实现(C/C++):

    /*
     * Introduction to Algorithms
     * Chapter 22 --- BFS
     * Tanky Woo @ www.WuTianQi.com
     * 2012.1.6
     */
    #include 
    #include 
    #define WHITE 0
    #define GRAY 1
    #define BLACK 2
    #define MAX 999999
    #define NIL 0
    
    using namespace std;
    
    int node;
    int G[100][100];
    int color[100];
    int dist[100];
    int prev[100];
    
    void BFS(int source)
    {
        for(int i=1; i<=node; ++i)
        {
            color[i] = WHITE;
            dist[i] = MAX;
            prev[i] = NIL;
        }
        color = GRAY;
        dist = 0;
        prev = NIL;
    
        queue que;
        que.push(source);
    
        while(!que.empty())
        {
            int no = que.front();
            que.pop();
            for(int i=1; i<=node; ++i)
                if(G[no][i]==1 && color[i]==WHITE)
                {
                    color[i] = GRAY;
                    dist[i] = dist[no] + 1;
                    prev[i] = no;
                    que.push(i);
                }
            color[no] = BLACK;
        }
    
    }
    
    void printPath(int source, int dest)
    {
        if(source == dest)
            cout << source;
        else if(prev[dest] == NIL)
            cout << "No path from " << source << " to " << dest << " exist
    ";
        else
        {
            printPath(source, prev[dest]);
            cout << " " << dest;
        }
    
    }
    
    int main()
    {
        freopen("input.txt", "r", stdin);
    
        memset(G, 0, sizeof(G));
        cout << "Input the number of the node:
    ";
        cin >> node;
        cout << "Input the Graph:
    ";
        for(int i=1; i<=node; ++i)
            for(int j=1; j<=node; ++j)
                cin >> G[i][j];
        BFS(2);
    
        cout << dist[4] << endl;
        cout << "The path: ";
        printPath(2, 4);
    
    }
    

    这是input.txt的内容:

    8
    0 1 0 0 0 0 0 1
    1 0 0 0 0 0 1 0
    0 0 0 1 0 1 1 0
    0 0 1 0 1 1 0 0
    0 0 0 1 0 1 1 0
    0 0 1 1 1 0 0 0
    0 1 1 0 1 0 0 0
    1 0 0 0 0 0 0 0

    可以看到结果,源点(2号)到u点(4号)的距离是3.

    源码我上传到我的网盘了:

    http://www.kuaipan.cn/file/id_35241628297855049.html

    DFS(深搜):

    深搜既深度优先搜索,相对于BFS,它是尽可能深的去搜索一个图。

    在DFS中,仍然用到了WHITE, GRAY,BLACK,但是它们的用处和BFS有些不同,这里他们是用来表示时间戳,因为DFS会有回溯,所以也就有第一次和第二次搜到。(具体见P330面)

    看P331面图22-4。

    具体实现(C/C++):

    /*
     * Introduction to Algorithms
     * Chapter 22 --- DFS
     * Tanky Woo @ www.WuTianQi.com
     * 2012.1.6
     */
    
    #include 
    #include 
    #define WHITE 0
    #define GRAY 1
    #define BLACK 2
    #define NIL 0
    
    using namespace std;
    
    int node;
    int G[100][100];
    int color[100];
    int fir[100], sec[100];  // 用来记录前后时间戳
    int prev[100];
    int time;   // time用来记录时间戳
    
    void DFS_VISIT(int no)
    {
        color[no] = GRAY;   // 当点no第一次被搜到
        ++time;
        fir[no] = time;
        for(int i=1; i<=node; ++i)
        {
            if(G[no][i]==1 && color[i]==WHITE)
            {
                prev[i] = no;
                DFS_VISIT(i);
            }
        }
        color[no] = BLACK;    // 当点no深搜完回溯时再次搜到
        sec[no] = ++time;
    
    }
    
    void DFS()
    {
        for(int i=1; i<=node; ++i)
        {
            if(color[i] == WHITE)
                prev[i] = NIL;
        }
        time = 0;
        for(int i=1; i<=node; ++i)
        {
            if(color[i] == WHITE)
                DFS_VISIT(i);
        }
    }
    
    int main()
    {
        freopen("input.txt", "r", stdin);
    
        memset(G, 0, sizeof(G));
        cout << "Input the number of the node:
    ";
        cin >> node;
        cout << "Input the Graph:
    ";
        for(int i=1; i<=node; ++i)
            for(int j=1; j<=node; ++j)
                cin >> G[i][j];
    
        DFS();
        cout << "点v(2号)的first:" << fir[2] << " 和second:" << sec[2] << endl;
    }
    

    这是input.txt的内容:

    6
    0 1 0 0 0 1
    0 0 0 0 1 0
    0 0 0 1 1 0
    0 0 0 1 0 0
    0 0 0 0 0 1
    0 1 0 0 0 0

    可以看到结果,点v(2号)的first和second分别是2和7

    源码我上传到我的网盘了:

    http://www.kuaipan.cn/file/id_35241628297855052.html

    (拓扑排序下次再写吧)

    小结:

    DFS和BFS是图算法的根本,但是刚开始了解可能不太习惯,建议找一些相应的题目来试试手。可以在我Blog搜BFS和DFS,可以找到我曾经做过的题目。

  • 相关阅读:
    php 导出csv文件
    dns 服务器配置
    ettercap ARP dns 欺骗
    for循环内 执行$ajax(){}
    js 如何生成二维数组
    jquery读取csv文件并用json格式输出
    echo 换行
    cmd命令运行php,php通过cmd运行文件
    Git 常用命令整理
    图像裁剪插件
  • 原文地址:https://www.cnblogs.com/downtjs/p/3424386.html
Copyright © 2020-2023  润新知