图的基本知识及实现_邻接矩阵_邻接表

原创 2016年05月30日 14:17:24

对于有 nn 个顶点的图 G = (V, E)来说,我们可以用一个 n * n的矩阵 AA来表示 G中各顶点的相邻关系,如果 v_{i}和 v_{j}之间存在边(或弧),则
A[i][j] = 1,
否则 A[i][j] = 0。
下图为有向图 G_{1}G1
​​ 以及对应的邻接矩阵。

这里写图片描述这里写图片描述

下图为无向图 G_{2}G2
​​ 以及对应的邻接矩阵。

这里写图片描述这里写图片描述

图的邻接矩阵是唯一的,矩阵的大小只与顶点个数 NN 有关,是一个 N * NN∗N 的矩阵。前面我们已经介绍过,在无向图里,如果顶点 v_{i}vi
v_{j}v​j之间有边,则可认为顶点 v_{i}v​i到 v_{j}v​j有边,同时顶点 v_{j}v​j到 v_{i}v​i 也有边。对应到邻接矩阵里,
则有
A[i][j]=A[j][i]=1。
因此我们可以发现,无向图的邻接矩阵是一个对称矩阵。

在邻接矩阵上,我们可以直观的看出两个顶点之间是否有边(或弧),并能容易求出每个顶点的度,入度和出度。

这里我们以图 G_{1}G​1为例,演示下如何利用邻接矩阵计算顶点的入度和出度。顶点的出度,即为邻接矩阵上点对应行上所有值的总和,比如顶点 1 对应的出度即为
0+1+1+1=3;而每个点的入度即为点对应列上所有值的总和,比如顶点 3 对应的入度即为
1+0+0+1=2。

这里写图片描述这里写图片描述

我们再来学习邻接表

邻接表是图的一种顺序存储与链式存储相结合的存储方法。我们给图 GG 中的每个顶点建立一个单链表,第 ii 个单链表中的结点表示依附于顶点 v_{i}​​ 的边(对于有向图是以 v_{i}为起点的弧)。所有单链表的表头结点都存储在一个一维数组中,以便于顶点的访问。下图为图 G_{1}对应的邻接表。

这里写图片描述
这里写图片描述

在无向图的邻接表中,顶点 v_{i}的度为第 i个单链表中的结点数;而在有向图中,第 ii 个单链表中的结点数表示的是顶点 v_{i}v
​i的出度,如果要求入度,则要遍历整个邻接表。另外,在邻接表中,我们很容易就能知道某一顶点和哪些顶点相连接。

学习完两种存储结构,可能你会有这样的疑问:那我们什么时候用邻接矩阵,什么时候用邻接表呢?

我们可以看到,邻接矩阵存储结构最大的优点就是简单直观,易于理解和实现。其适用范围广泛,有向图、无向图、混合图、带权图等都可以直接用邻接矩阵表示。另外,对于很多操作,比如获取顶点度数,判断某两点之间是否有连边等,都可以在常数时间内完成。

然而,它的缺点也是显而易见的:从以上的例子我们可以看出,对于一个有 n 个顶点的图,邻接矩阵总是需要n​2的存储空间。当边数很少的时候,就会造成空间的浪费。

因此,具体使用哪一种存储方式,要根据图的特点来决定:如果是稀疏图,我们一般用邻接表来存储,这样可以节省空间;如果是稠密图,考虑到邻接表中要附加链域,我们一般用邻接矩阵来存储

邻接表的创建

#include <iostream>
#include <cstring>
using namespace std;

class Graph {
private:
    int **mat;
    int n;

public:
    Graph(int input_n) {
        n = input_n;
        mat = new int*[n];
        for (int i = 0; i < n; ++i) {
            mat[i] = new int[n];
            memset(mat[i], 0, sizeof(int) * n);
        }
    }

    ~Graph() {
        for (int i = 0; i< n; ++i) {
            delete[] mat[i];
        }
        delete[] mat;
    }

    void insert(int x, int y) {
        mat[x][y]=1;
    }

    void output() {
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cout<<mat[i][j]<<" ";
            }
            cout<<endl;
        }

    }
};

int main() {
    int n, m, x, y;
    cin >> n >> m;
    Graph g(n);
    for (int i = 0; i < m; ++i) {
        cin >> x >> y;
        g.insert(x, y);
    }
    g.output();
    return 0;
}

邻接表

#include <iostream>
using namespace std;

class LinkedListNode {
public:
    int vertex;
    LinkedListNode *next;

    LinkedListNode(int vertex_input) {
        vertex = vertex_input;
        next = NULL;
    }
};

class LinkedList {
public:
    LinkedListNode *head;

    LinkedList() {
        head = NULL;
    }

    ~LinkedList() {
        while (head != NULL) {
            LinkedListNode *delete_node = head;
            head = head->next;
            delete delete_node;
        }
    }

    void insert(int vertex) {
        LinkedListNode *node = new LinkedListNode(vertex);
        node->next = head;
        head = node;
    }
};

class Graph {
private:
    LinkedList *edges;
    int n;
public:
    Graph(int input_n) {
        n = input_n;
        edges = new LinkedList[n];
    }

    ~Graph() {
        delete[] edges;
    }

    void insert(int x, int y) {
        edges[x].insert(y);
    }

    void output() {
        for(int i=0;i<n;i++){
            cout<<i<<":";
            for(auto j=edges[i].head;j!=NULL;j=j->next){
                cout<<j->vertex<<" ";
            }
            cout<<endl;
        }
    }
};

int main() {
    int n, m, x, y;
    cin >> n >> m;
    Graph g(n);
    for (int i = 0; i < m; ++i) {
        cin >> x >> y;
        g.insert(x, y);
    }
    g.output();
    return 0;
}
版权声明:ShirleyPaul原创,未经博主允许不得转载

相关文章推荐

图基本算法 ,图的表示方法 邻接矩阵 邻接表

邻接表: 要表示一个图G=(V,E),有两种标准的表示方法,即邻接表和邻接矩阵。这两种表示法既可用于有向图,也可用于无向图。通常采用邻接表表示法,因为用这种方法表示稀疏图(图中边数远小于点个数)...
  • tham_
  • tham_
  • 2015-05-27 16:01
  • 1210

图的深度优先遍历DFS(分别以邻接矩阵和邻接表实现)

#include using namespace std; #define MAX_VEX_NUM 50 typedef char VertexType; typedef enum{ UDG...

图的广度优先搜索(BFS)、深度优先搜索(DFS)(邻接矩阵法和邻接表法java实现)

图的广度优先搜索(BFS)、深度优先搜索(DFS) package ccnu.offer.graph;import java.util.ArrayList; import java.util.Arra...

图的API及其两种实现(邻接矩阵,邻接表 )

常见的实现有 邻接矩阵法 和邻接表法。 注意图上的算法 和图本书的存储方式是无关的, 很多书都没有严格区分这一点。 图上的算法 比如 最小生成树 最短路径 遍历 拓扑排序等,仅依赖与API而不是图的...

图的遍历(BFS、DFS的邻接矩阵和邻接表实现)

当年老师给我们讲这里的时候,讲的真是云里雾里的。 。其实画个图就很容易理解的事情,为什么扯那么远 我觉得 DFS其实就是树的先序遍历的强化版本 BFS是层序遍历的强化 只不过 图的实现...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)