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

来源:互联网 发布:人工智能分析用户行为 编辑:程序博客网 时间:2024/05/22 13:05

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

图的定义:
图是一种数据结构,和树一样可以用二元组表示。它可定义为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的所有邻接点构成一个线性表,由于邻接点的个数不定,所以,用链表存储。链表中每个节点有两个信息:当前顶点的下标,指向下一节点的指针。在该图中,数组里面的下标对应不同的顶点,而链表里的节点对应这个顶点的邻接点。
这里写图片描述

图的遍历:
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。
这里写图片描述

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

//本实例通过建立邻接矩阵来遍历图#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 1typedef 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

0 0
原创粉丝点击