重新教自己学算法之图的遍历(十一)—深度(DFS)和广度(BFS)

好几天没有补算法了。以前对于图的各种算法没有学好,特此机会重新复习一下图的基本算法。

图的定义:
图是一种数据结构,和树一样可以用二元组表示。它可定义为Graph=(V,R)其中,V={x|x∈datatype},R={VR},VR={(x,y)|P(x,y)∧(x,y∈V)}, V是顶点的非空有穷集合,R是边的有穷集合。
也就是说说,图就是记录一些点和点之间的关系的数据结构。

图的存储:
 1:邻接矩阵:一个二维数组,不同下标对应着不同的点。分为无向图和有向图。如果是无向图,vi<->vj 即 graph[vi][vj] = graph[vj][vi] = 1; 有向图 vi->vj 则只有graph[vi][vj] = 1。如果边上有权重val,则graph[vi][vj] = val。
 而虽然邻接矩阵在记录边关系时很方便,但是面临的问题是浪费大量空间,特别是面对稀疏图(即图中边的数量大大少于节点数量)时,问题尤其明显。因为我们的示例图很简单,所以接下来我用的都是邻接矩阵。
2:邻接表:
邻接表的出现解决了邻接矩阵的问题,即使用了链式结构。 邻接表的处理方法是这样的:
(1):图中顶点用一个一维数组存储。
(2):图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用链表存储。链表中每个节点有两个信息:当前顶点的下标,指向下一节点的指针。在该图中,数组里面的下标对应不同的顶点,而链表里的节点对应这个顶点的邻接点。
《重新教自己学算法之图的遍历(十一)—深度(DFS)和广度(BFS)》

图的遍历:
1:深度优先搜索(DFS):注重的是深度优先。
拿上图举例,我们从v1出发,如果我们先走左边的顶点(这个左边在程序里即第一个顶点),我们走到了v2,发现还能往下(下的意思是有邻接点存在)走,走左边到了v4,发现有岔路口,但是v1我们走过了,只能走v5,v5走到了v3。此时全部点都遍历了一遍,即DFS完成。顺序:v1,v2,v4,v5,v3。
2:广度优先搜索(BFS):注重广度,按层次遍历。
即先把眼前的地方先走一遍,再接着遍历更远的地方。拿上图举例。我们从v1出发,首先把眼前的顶点遍历完(即遍历v1所有的邻接点),我们遍历了v2,v3,v4。然后从最左边的顶点接着重复此过程,遍历了v5。此时全部点都遍历了一遍,即BFS完成。顺序:v1,v2,v3,v4,v5。
《重新教自己学算法之图的遍历(十一)—深度(DFS)和广度(BFS)》

了解基本思想,仔细阅读源代码,并动手运算一遍。

//本实例通过建立邻接矩阵来遍历图

#include <iostream>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <queue>
using namespace std;

#define MAX 100
#define max(x,y)(x > y ? x : y)
//这里假设我们从顶点1开始遍历
#define initNode 1
typedef struct{
    int matrix[MAX][MAX];
    int num;
}Graph;

Graph example;

void createPoint()
{
    int i, j;
    //图的初始化
    memset(example.matrix, 0 ,sizeof(example.matrix));
    example.num = 0;
    while(cin>>i>>j && i != 0 && j != 0)
    {
        example.matrix[i][j] = 1;
        example.matrix[j][i] = 1;

        //出现的最大数即为最大顶点数
        example.num = max(example.num, i);
        example.num = max(example.num, j);
    }
}

void DFS(int x, int* visited)
{
    cout<<" "<<x;
    for(int i = 1; i <= example.num; i++)
    {
        if (visited[i] == 0 && example.matrix[x][i] == 1)
        {
            visited[i] = 1;
            DFS(i, visited);
        }
    }
}

void BFS()
{
    int i, nNode;
    queue<int> gQueue;
    int* visited = new int[example.num++];
    memset(visited, 0, sizeof(int)*(example.num++));//此处的*为乘号

    cout<<"BFS"<<"------------------"<<endl;
    visited[initNode] = 1;
    gQueue.push(initNode);

    while(!gQueue.empty())
    {
        nNode = gQueue.front();
        cout<<" "<<nNode;
        for (int i = 1; i <= example.num; ++i)
        {
            if(example.matrix[nNode][i] == 1 && visited[i] == 0)
            {
                gQueue.push(i);
                visited[i] = 1;
            }
        }
        gQueue.pop();
    }
    cout<<endl<<"--------------"<<endl;
}

void initDFS()
{
    int* visited = new int[example.num++];
    memset(visited, 0, sizeof(int)*(example.num++));
    cout<<"DFS"<<"----------------"<<endl;
    visited[initNode] = 1;
    DFS(initNode,visited);

    cout<<endl<<"DFS"<<"----------------"<<endl;
}

void test()
{
    createPoint();
    cout<<example.num<<endl;
    BFS();
    initDFS();
}

int main(int argc, char const *argv[])
{
    test();
    return 0;
}

参考文章:http://blog.csdn.net/u010006643/article/details/45673571

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/u012935756/article/details/46403669
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞