zoukankan      html  css  js  c++  java
  • 图的表示、广度优先搜索、深度优先搜索

    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的前驱子图是有多颗树组成的深林.

    结点颜色的含义:

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

    遍历路径:

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

  • 相关阅读:
    SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法
    Spring data jpa 使用技巧记录
    Hibernate 关于实体映射常用注解
    Mysql数据库实用语句集
    免配置环境变量使用Tomcat+设置项目主页路径为http://localhost:8080+修改tomcat端口号
    Springboot+shiro配置笔记+错误小结
    python阳历转农历
    Aria2+WebUI+caddy搭建私有网盘
    java运算符优先级
    IntelliJ IDEA 快捷键
  • 原文地址:https://www.cnblogs.com/bukekangli/p/4394504.html
Copyright © 2011-2022 走看看