图的常用存储结构

一、邻接矩阵

  邻接矩阵是简单的也是比较常用的一种表示图的数据结构,对于一个有N个点的图,需要一个N*N的矩阵,这个矩阵的i行第j列的数值表示点vi到点vj的距离。邻接矩阵需要初始化,map[i][i] = 0;map[i][j] = INF(i != j),对于每组读入的数据vi,vj,w(vi为边的起点,vj为边的终点,w为边的权值),赋值map[vi][vj] = w,另外邻接矩阵的值和边的输入顺序无关。

  对于邻接矩阵来说,初始化需要O(n^2)的时间,建图需要O(m),所以总时间复杂度是O(n^2),空间上,邻接矩阵的开销也是O(n^2),和点的个数有关。

二、前向星

  前向星是一种通过存储边的方式来存储图的数据结构。构造的时候,只需要读入每条边的信息,将边存放在数组中,把数组中的边按照起点顺序排序,前向星就构造完毕,为了查询方便,经常会有一个数组存储起点为vi的第一条边的位置.

  由于涉及排序,前向星的构造时间复杂度与排序算法有关,一般情况下时间复杂度为O(mlogN),空间上需要两个数组,所以空间复杂度为O(m + n),有点在于可以应对点非常多的情况,可以存储重边,但是不能直接判断任意两个顶点之间是否有边.

 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 using namespace std;
 8 typedef long long LL;
 9 
10 const int MAXN = 1000 + 3;
11 int head[MAXN]; //存储起点为Vi的边第一次出现的位置
12 
13 struct NODE
14 {
15     int from;
16     int to;
17     int w;
18 };
19 NODE edge[MAXN];
20 
21 bool cmp(NODE a, NODE b)
22 {
23     if(a.from == b.from && a.to == b.to) return a.w < b.w;
24     if(a.from == b.from) return a.to < b.to;
25     return a.from < b.from;
26 }
27 
28 int main()
29 {
30     freopen("input.txt", "r", stdin);
31     int n,m;
32     cin >> n >> m;
33     for(int i = 0; i < m; i++)
34     {
35         cin >> edge[i].from >> edge[i].to >> edge[i].w;
36     }
37     sort(edge, edge + m, cmp);
38     memset(head, -1, sizeof(head));
39     head[edge[0].from] = 0;
40     for(int i = 1; i < m; i++)
41     {
42         if(edge[i].from != edge[i - 1].from)
43         {
44             head[edge[i].from] = i;
45         }
46     }
47     for(int i = 1; i <= n; i++)
48     {
49         for(int k = head[i]; edge[k].from == i && k < m; k++)
50         {
51             cout << edge[k].from << ' ' << edge[k].to << ' ' << edge[k].w <<endl;
52         }
53     }
54     for(int i = 0; i <= n; i++)
55     {
56         cout << head[i] << " ";
57     }
58     cout << endl;
59     return 0;
60 }

三、链式前向星

  链式前向星采用数组模拟链表的方式实现邻接表的功能,并且使用很少的额外空间,是当前建图和遍历效率最高的存储方式.数组模拟链表的主要方式是记录下一个节点的数组的在哪一个位置。head数组存储描述点vi边信息的链的起点在Edges数组的位置。构造链式前向星就是将新加入的节点链对应链的最开始并修改head数组的对应位置的值.

  链式前向星的建图时间复杂度为O(m),空间上为O(m + n)。

 1 //链式前向星
 2 const int maxN = 100 + 3;
 3 const int maxM = 1000 + 3;
 4 int head[maxN];
 5 int N, M;
 6 
 7 struct EdgeNode
 8 {
 9     int to;   //边的后继
10     int w;    //权值
11     int next;     //指向下一条边的位置
12 };
13 EdgeNode Edges[maxM];
14 
15 int main()
16 {
17     //freopen("input.txt", "r", stdin);
18     memset(head, -1, sizeof(head));
19     cin >> N >> M;  //N个点,M条边
20     for(int i = 1; i <= M; i++)
21     {
22         int x, y ,z;
23         cin >> x >> y >> z;
24         Edges[i].to = y;
25         Edges[i].w = z;
26         Edges[i].next = head[x];
27         head[x] = i;
28     }
29     return 0;
30 }
31 
32 void traversal()
33 {
34     for(int i = 1; i <= N; i++)
35     {
36         for(int k = head[i]; k != -1; k = Edges[k].next)
37         {
38             cout << i << ' ' << Edges[k].to << ' ' << Edges[k].w << endl;
39         }
40     }
41 }
原文地址:https://www.cnblogs.com/Ash-ly/p/5397941.html