signed

QiShunwang

“诚信为本、客户至上”

图的表示形式:邻接矩阵和邻接表

2021/3/21 8:53:39   来源:

 

图是对象和对象之间存在的关系的有限集合。如果将对象表示为顶点(或节点),将关系表示为边,则可以得到以下两种图形:

有向图:在有向图中,一条边由一对有序的顶点(i,j)表示,其中边起源于顶点i并终止于顶点j。下面给出的是有向图的示例。

 
 

图:D.1

无向图:在无向图中,边由无序顶点对表示。下面给出了无向图的示例。

图:UD.1

表示

表示图形的两种最常见方式是:
1.邻接矩阵
2.邻接表

邻接矩阵

让我们考虑一个图,其中有从0到N-1编号的N个顶点和(i,j)形式的E个边。其中(i,j)表示源自i顶点并终止于j顶点的边。现在,A邻接矩阵是一个N * N的二进制矩阵,其中的值[I,J]细胞是1,如果有从存在的边缘始发顶点并终止于Ĵ顶点,否则该值0。下面给出的是上面显示的有向图和无向图的邻接矩阵:

 

有向图的邻接Matix :(对于图:D.1)

无向图的邻接Matix :(对于图:UD.1)

 

伪码

构造邻接矩阵的伪代码如下:

1. Create a matrix A of size NxN and initialise it with zero.
2. Iterate over each given edge of the form (u,v) and assign 1 to A[u][v]. Also, If graph is undirected then assign 1 to A[v][u]. 
执行

   /*
      This code is for constructing adjacency matrix for undirected graph, with minor change it will also work for directed graph.
   */
   #include <bits/stdc++.h>
   using namespace std;
   int main()
   {
       // where n is number of vertices and m is number of edges
   int n, u, v, m;
   cin>> n>> m;
   int A[n][n];
   for(int i=0; i&lt;n; i++)
   {
        for(int j=0; i&lt;n; j++)
            A[i][j]=0;
   } 
   for(int i=0; i&lt; m; i++)
   {
       cin>> u>> v;
       A[u][v]=1;
       A[v][u]=1; // In case of directed graph this statement is removed. 
   }
   // After above loop Adjcency matrix is ready.
    for(int i=0; i&lt;n; i++)
   {
        for(int j=0; j&lt;n; j++)
            cout&lt;&lt;A[i][j]&lt;&lt;" ";
        cout &lt;&lt; "\n";
   } 
   return 0;
 }

 

C ++
复制

 

邻接表

让我们考虑一个图,其中有从0到N-1编号的N个顶点,并且以(i,j)的形式有E个边。其中(i,j)表示从i顶点到j顶点的边。现在,邻接列表是一个单独列表的数组。数组的每个元素都是对应的相邻(或直接连接)顶点的列表。换句话说,邻接列表的i列表是所有直接连接到i顶点的所有顶点的列表。下面给出的是上面显示的有向图和无向图的邻接列表:

 

有向图的邻接表:(对于图:D.1)

无向图的邻接表:(对于图:UD.1)

 

伪码
构造邻接矩阵的伪代码如下:
1. Create an array A of size N and type of array must be list of vertices. Intially each list is empty so each array element is initialise with empty list.
2. Iterate each given edge of the form (u,v) and append v to the uth list of array A. Also, If graph is undirected append u to the vth list of array A.

执行


   /*
      This code is for constructing adjacency list for undirected graph, with minor change it will also work for directed graph.
   */
   #include <bits/stdc++.h>
   using namespace std;
   int main()
   {
       // where n is number of vertices and m is number of edges
       int n, u, v, m;
       cin>> n>> m;
       vector< vector<int> > A(n);
       for(int i=0; i< m; i++)
       {
           cin>> u>> v;
           A[u].push_back(v);
           A[v].push_back(u); // In case of directed graph this statement is removed. 
       }
       // After above loop Adjcency List is ready.
        for(int i=0; i<n; i++)
       {
            cout<< i<< " ----> ";
            for(int j=0; j<A[i].size(); j++)
                cout<< A[i][j]<< " -->";
            cout <<  "\n";
       } 
       return 0;
     }
 

复杂

 

N表示节点/顶点的数量,M表示边的数量

degree(V)表示从节点V开始的边数

邻接矩阵复杂度

 

空间: O(N * N)

检查节点U和V之间是否存在边缘: O(1)

查找节点的所有边缘: 在)

 

邻接表复杂度

 

空间: O(N + M)

检查节点U和V之间是否存在边缘: O(度(V))

查找节点V的所有边: O(度(V))

在哪里使用?

正如我们在复杂度比较中所看到的那样,两种表示形式都有其优缺点,并且两种表示形式的实现都很简单。建议我们使用邻接矩阵表示密集图,并使用邻接表表示稀疏图。

注意:密集图是那些具有大量边的图,而稀疏图是那些具有少量边的图。

应用

  1. 邻接矩阵:邻接矩阵用于以下位置,有关每个可能的边的信息对于算法的正确工作是必需的:-Floyd-Warshall算法,其中计算从每个顶点到每个其他顶点的最短路径(如果存在)。它也可以用在DFS(深度优先搜索)和BFS(宽度优先搜索)中,但是列表在那里更有效。有时它也用于网络流中。

  2. 邻接列表:邻接列表是一种节省空间的图形表示方法,如果算法不需要显式要求,则可以在几乎所有位置替换邻接矩阵。它用于诸如BFS,DFS,Dijkstra算法等的地方。