• 图-基础


    1. 图的表示:

    1)邻接矩阵:

    a. 表示无向图:

    b. 表示无向图:

    #include<stdio.h>
    #include<stdlib.h>
    #include<vector>
    #include<iostream>
    #include<assert.h>
    using namespace std;
    
    //稠密图 - 邻接矩阵
    class DenseGraph {
    private:
        int n, m;  //顶点,边
        bool directed;   //有向或无向
        vector<vector<bool>> g;   //邻接矩阵
    
    public:
        DenseGraph(int n, bool directed) {
            this->n = n;
            this->m = 0;
            this->directed = directed;
            for (int i = 0; i < n; i++) {
                g.push_back(vector<bool>(n, false));
            }
        }
        ~DenseGraph()
        {
    
        }
        int V() { return n; }  //返回顶点数
        int E() { return m; }  //返回边数
    
        void addEdge(int v, int w) {
            assert(v >= 0 && v < n);
            assert(w >= 0 && w < n);
    
            if (hasEdge(v, w))
                return;   //若已经有边,直接return
    
            g[v][w] = true;  //有向图
    
            if (v!=w &&!directed) {
                //无向图
                g[w][v] = true;
            }
            m++;
        }
        bool hasEdge(int v, int w) {
            //判断v和w之间是否已经存在边 (不包括平行边)
            assert(v >= 0 && v < n);
            assert(w >= 0 && w < n);
            return g[v][w];  //返回为true或false
        }
    };

     2)邻接表:

    a. 无向图:

    第一行:0 和 1 相连;

    第二行:1 和 0,2,3 相连;

    第三行:2 和 1,3 相连;

    第四行:3 和 1,2 相连。

    b. 有向图:

     邻接表适合表示一个稀疏的图, 邻接矩阵适合表示一个稠密的图。

     若有平行边,邻接表会最多需要O(n)的时间复杂度, 去把平行边消除。

    #include<stdio.h>
    #include<stdlib.h>
    #include<vector>
    #include<iostream>
    #include<assert.h>
    using namespace std;
    
    //稀疏图 - 邻接表
    class SparseGraph {
    private:
        int n, m;  //顶点,边
        bool directed;   //有向或无向
        vector<vector<int>> g;   // 邻接表 每一行存储的是顶点编号
    
    public:
        SparseGraph(int n, bool directed) {
            //构造函数来初始化
            this->n = n;
            this->m = 0;
            this->directed = directed;
            for (int i = 0; i < n; i++) {
                g.push_back(vector<int>() );
            }
        }
        ~SparseGraph()
        {
    
        }
        int V() { return n; }
        int E() { return m; }
    
        void addEdge(int v, int w) {
            assert(v >= 0 && v < n);
            assert(w >= 0 && w < n);
    
            if (hasEdge(v, w))
                return;   //若已经有边,直接return
    
            g[v].push_back(w);  //v和w相连
    
            if (v!=w && !directed) {
                //无向图(不自环)
                g[w].push_back(v);
            }
            m++;
        }
        bool hasEdge(int v, int w) {
            //判断v和w之间是否存在边
            assert(v >= 0 && v < n);  //判断v和w不越界
            assert(w >= 0 && w < n);
    
            for (int i = 0; i < g[v].size();i++) { //O(n)复杂度 寻找平行边
                if (g[v][i] == w)
                    return true;
                return false;
            }
            return g[v][w];  //返回为true或false
        }
    };

    2. 遍历邻边

    邻接矩阵遍历临边需要O(v)的时间复杂度,v为顶点个数。

    所以最好使用邻接表。

    用BFS和DFS来遍历图:

    #字典
    graph ={
        "A":["B","C"],
        "B":["A","C","D"],
        "C":["A","B","D","E"],
        "D":["B","C","E","F"],
        "E":["C", "D"],
        "F":["D"]
    }
    def BFS(graph, s):    #s起点
        queue = []
        queue.append(s)
        seen = set()
        seen.add(s)
        
        while(len(queue)>0):
            vertex = queue.pop(0)   #取出队首元素
            nodes = graph[vertex]
            for w in nodes:
                if w not in seen:
                    queue.append(w)
                    seen.add(w)
            print (vertex)

    输出:

    BFS(graph, "A")

    DFS:

    def DFS(graph, s):    #s起点
        stack = []
        stack.append(s)
        seen = set()
        seen.add(s)
        
        while(len(stack)>0):
            vertex = stack.pop()   #取出队首元素
            nodes = graph[vertex]
            for w in nodes:
                if w not in seen:
                    stack.append(w)
                    seen.add(w)
            print (vertex)
    DFS(graph, "A")

    输出所有结点的父亲:

    def BFS(graph, s):    #s起点
        queue = []     #数组
        queue.append(s)
        seen = set()    #集合
        seen.add(s)
        parent = {s: None}     #字典 来记录某个结点的父亲,起始点的父亲为空
        
        while(len(queue)>0):
            vertex = queue.pop(0)   #取出队首元素
            nodes = graph[vertex]
            for w in nodes:
                if w not in seen:
                    queue.append(w)
                    seen.add(w)
                    parent[w] = vertex
            #print (vertex)
        return parent
    parent = BFS(graph, "A")
    for key in parent:
        print(key, parent[key])

  • 相关阅读:
    技术晨读_2015_11_29
    mysql的timeout
    Gradle目录解析
    flexbox简介
    elasticsearch 查询(match和term)
    内存那些事
    elasticsearch 文档
    elasticsearch 集群
    elasticsearch中的API
    小菜的程序员道路(三)
  • 原文地址:https://www.cnblogs.com/Bella2017/p/10700712.html
Copyright © 2020-2023  润新知