图的表示、广度优先搜索、深度优先搜索

1.图的表示

a.邻接矩阵:适合稠密图(|E|接近|V|2)

//用二维数组表示邻接矩阵
int G[|V|][|V|];
//初始化
for(int i=0;i<|V|;i++){
    for(int j=0;j<|V|;j++){
        if( (i,j) in E){
            G[i][j] = 1;//or G[i][j] = weight[i][j];
        }
        else if(i==j){
            G[i][j] = 0;
        }
        else{
            G[i][j] = MAX;
        }
    }
}

b.邻接表:适合稀疏图(|E|远小于|V|2)

//邻接表的表示
class Node{
public:
    int index;//顶点索引
    Node* next=nullptr;//下一顶点
    Node(int i):index(i){}
};
class VNode{
public:
    char vertex;//顶点
    int index;//顶点索引
    int dist;//BFS:表示顶点到源点的距离,DFS:表示顶点第一次被发现的时间
    int finish;//BFS:无意义,DFS:表示顶点的邻接表扫描完成时的时间
    Color color;//顶点颜色
    int prev;//顶点的前驱
    Node* firstNode=nullptr;//第一条边的尾节点
    VNode(char c,int i):vertex(c),index(i){}
};
class Graph{
    vector<VNode> Adj;//所有顶点
};
//初始化
void AddEdge(Graph &G,int i,int j,int weight,int w[][|V|]){
    Node* p = new Node(j);
    p->next = G.Adj[i].firstNode;
    G.Adj[i].firstNode = p;
    w[i][j]=weight;
        //有向图只需上面部分代码即可
    Node* p2 = new Node(i);
    p2->next = G.Adj[j].firstNode;
    G.Adj[j].firstNode = p2;
    w[j][i] = weight;
}
//初始化顶点
for(int i=0;i<|V|;i++){
    G.Adj.push_back(VNode(V[i], i));
}
//初始化边、权重
int w[6][6];
for (int i = 0; i < 6; ++i){
    for (int j = 0; j < 6; ++j){
        if(i == j){
            w[i][j] = 0;
        }
        else{
            w[i][j] = MAX;
        }
    }
}
for (i,j) in E:
    AddEdge(G,i,j,weight[i][j],w);

2.广度优先搜索BFS

思路:从某个源点开始遍历图,先将源点颜色置为灰色,然后将其加入队列Q,对Q中的元素进行如下循环操作:

1.从队列Q中弹出一个元素u
2.访问与u相邻的每个顶点v,若v的颜色为白色(未被发现)
    则将v的颜色置为灰色
    v与源点的距离更新为u到源点距离加1
    v的前驱更新为u
    将v压入队列Q
3.u的邻接表扫描完成,将u的颜色置为黑色

直至Q为空.

伪代码:

BFS(G,s)
    for each vertex u in G.V
        u.color = white
        u.d = MAX
        u.p = NIL
    s.color = gray
    s.d = 0
    s.p = NIL
    Q = ∅
    ENQUEUE(Q,s)
    while Q ≠ ∅
        u = DEQUEUE(Q)
        for each v in G.Adj[u]
            if v.color == white
                v.color = gray
                v.d = u.d+1
                v.p = u
                ENQUEUE(Q,v)
        u.color = black

时间复杂度:O(V+E)

打印源节点s到结点v的一条路径上的所有节点

PrintPath(G,s,v)
    if v==s
        print s
    else if v.p == NIL
        print "No such path"
    else
        PrintPath(G,s,v.p)
        print v

对于每个从源结点s可以到达的结点v,广度优先搜索里从结点s到结点v的简单路径就是图G中从结点s到结点v的"最短路径".

3.深有优先搜索DFS

思路:对每一个顶点u,若u的颜色为白色,则对u进行深度优先访问(DFS-VISIT)

1.全局时间戳time加1,u被发现的时间更新为time,u的颜色更新为灰色
2.访问与u相邻的每个顶点v,若v的颜色为白色(未被发现)
    v的前驱更新为u
    对v进行深度优先访问
3.u的邻接表扫描完成,u的颜色置位黑色,time加1,u的邻接表扫描完成时间更新为time

一次深度优先访问可能无法访问到所有顶点,这正是要对每个顶点进行深度优先访问的原因.

伪代码:

DFS(G)
    for each vertex u in G.V
        u.color = white
        u.p = NIL
    time  = 0
    for each vertex u in G.V
        if u.color == white
            DFS-VISIT(G,u)
DFS-VISIT(G,u)
    time = time +1//u has just been discovered
    u.d = time
    u.color = gray
    for each v in G.Adj[u]//explore edge(u,v)
        if v.color == white
            v.p = u
            DFS-VISIT(G,v)
    u.color = black//blacken u,it is finished
    time = time +1
    u.f = time

时间复杂度:O(V+E)

BFS和DFS的区别:

BFS的前驱子图是一棵树,DFS的前驱子图是有多颗树组成的深林.

结点颜色的含义:

初始时未被发现是白色,被发现后为灰色,其邻接表被扫描完成后为黑色.

遍历路径:

若要得到图的遍历顺序,可在结点被访问后保存到一个向量.

时间: 2024-11-05 00:14:53

图的表示、广度优先搜索、深度优先搜索的相关文章

数据结构--图--图的数组存储表示,深度优先搜索遍历和广度优先搜索遍历

图有四种存储结构:数组,邻接表,十字链表,邻接多重表.下面以数组为存储结构来实现图的深度优先搜索遍历和广度优先搜索遍历.其中广度优先搜索遍历中有用到STL中的queue,注意头文件的包含.具体代码如下: //图的数组(邻接矩阵)存储表示和深度优先遍历 const int MAX_VERTEX_NUM=20; //最大顶点数 typedef enum {DG,DN,UDG,UDN} GraphKind ;//(有向图,有向网,无向图,无向网) typedef int VRType; typedef

POJ 2196 Computer(搜索-深度优先搜索)

Computer Problem Description A school bought the first computer some time ago(so this computer's id is 1). During the recent years the school bought N-1 new computers. Each new computer was connected to one of settled earlier. Managers of school are

图的邻接表法深度优先搜索

# include <stdio.h> # include <stdlib.h> # define True 1 # define False 0 # define Error -1 # define OK 1 # define MAX_VERTEX_NUM 20 int visited[MAX_VERTEX_NUM];                       //定义标志数组 typedef char VertexData; typedef enum{DG,DN,UDG,UD

挑战程序2.1.4 穷竭搜索&gt;&gt;深度优先搜索

{'W','.','.','W','.'}, {'W','.','.','.','.'}, {'.','.','.','W','.'}, {'W','.','.','.','.'}, {'W','.','W','W','W'}例子,此处有5处积水 题目:有N*M格子的花园,W表示积水,'.'表示干地,积水附近8个区域只要有积水,那么这两处连通,并算作是同一处积水,问一共有几处积水? 思路:穷竭搜索,O(N*M),搜索到积水则变成'.',并搜索连通的积水将其变成'.',直到这块积水搜索结束,此时a

搜索——深度优先搜索(DFS)

设想我们现在身处一个巨大的迷宫中,我们只能自己想办法走出去,下面是一种看上去很盲目但实际上会很有效的方法. 以当前所在位置为起点,沿着一条路向前走,当碰到岔道口时,选择其中一个岔路前进.如果选择的这个岔路前方是一条死路,就退回到这个岔道口,选择另一个岔路前进.如果岔路口存在新的岔道口,那么仍然按上面的方法枚举新岔道口的每一条岔道.这样,只要迷宫存在出口,那么这个方法一定能够找到它. 也就是说,当碰到岔道口时,总是以"深度"作为前进的关键词,不碰到死胡同就不回头,因此这种搜索的方式称为深

图的邻接表表示、广度优先、深度优先搜索

图,就是我们在数据结构中学到的图,它是一种存储信息的结构.图是一类在实际应用中非常常见的数据结构,当数据规模大到一定程度时,如何对其进行高效计算即成为迫切需要解决的问题.最常见的大规模图数据的例子就是互联网网页数据,网页之间通过链接指向形成规模超过500 亿节点的巨型网页图.再如,Facebook 社交网络也是规模巨大的图,仅好友关系已经形成超过10 亿节点.千亿边的巨型图,考虑到Facebook 正在将所有的实体数据节点都构建成网状结构,其最终形成的巨型网络数据规模可以想见其规模.要处理如此规

挑战程序2.1.4 穷竭搜索&gt;&gt;深度优先搜索 练习题 POJ1979黑与红

http://poj.org/problem?id=1979 Description There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move

算法-无向图(深度优先搜索和广度优先搜索)

图中最常用到的两种搜索深度优先搜索和广度优先搜索,深度优先搜索是一种在开发爬虫早期使用较多的方法它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链接的Html文件) ,广度搜索属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果.换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止. 深度优先搜索 图中我们经常会遇到一个问题就是图的连通性,比如说从一个顶点到另外一个顶点,判断顶点和其他顶点之间的连通性,以下图为例: 搜索API定义: @interface

【图论】广度优先搜索和深度优先搜索

写在最前面的 这篇文章并没有非常详细的算法证明过程.导论里面有非常详细的证明过程.本文只阐述“广度优先和深度优先搜索的思路以及一些简单应用”. 两种图的遍历算法在其他图的算法当中都有应用,并且是基本的图论算法. 广度优先搜索 广度优先搜索(BFS),可以被形象的描述为“浅尝辄止”,具体一点就是每个顶点只访问它的邻接节点(如果它的邻接节点没有被访问)并且记录这个邻接节点,当访问完它的邻接节点之后就结束这个顶点的访问. 广度优先用到了“先进先出”队列,通过这个队列来存储第一次发现的节点,以便下一次的

人员分配问题(简单的深度优先搜索题目)

问题描述 某单位有若干人员,现执行某任务需要一定人数人员.编写程序,输入单位人数和每位员工名字,再输入执行任务所需人数,输出所有可能派出人员方案 程序代码 #include<bits/stdc++.h> using namespace std; char s[10][20]; //存放读进来的人的名字,暂定人最多为10个 char ans[10][20]; //存放每一次生成的结果 int maxMan = 0; //存放执行任务所需人数 int times = 0; //存放总方案数 int