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

原文链接:http://www.wutianqi.com/?p=3000

建议先看看前言:http://www.wutianqi.com/?p=2298

这一章都是一些图的基础概念和算法。

图的两种表示方法:1.邻接表 2.邻接矩阵

 

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\n";

    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:\n";

    cin >> node;

    cout << "Input the Graph:\n";

    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:\n";

    cin >> node;

    cout << "Input the Graph:\n";

    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,可以找到我曾经做过的题目。

你可能感兴趣的:(算法导论)