一、图的定义
如上图,该图为无向图,每一个圆称为顶点,连接每个顶点之间的线称为边,而图就是这些结点的关联这些结点的集合,在上图中,顶点的集合就是{0,1,2,3,4},边的集合就是{(0,1),(1,2),(0,3),(3,2),(2,4)};在无向图中,一个结点连边的条数称作这个结点的度数;在上图,由结点0到结点1,需要8点属性值,像这样的每一条边的属性值就是边权,当2个顶点之间不止一条边直线相连时,那么就称为重边。
相比上图,下图每条边上多了箭头,这种图就是有向图,有向图中只有2个顶点的起点和终点都一致时,这2条边才是重边。
二、图的存储
在没有重边的情况下,使用邻接矩阵存储图最直观
上图分别是一有向图和一无向图以及它们的邻接矩阵
邻接矩阵代码如下
#include<iostream>
#define MAXN 1005;//图的最大点数
using namespace std;
int n;
int v[MAXN][MAXN];
int main(){
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cin >> v[i][j];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (v[i][j] > 0)
cout << "edge from point " << i << " to point " << j << " with length " << v[i][j] << endl;
return 0;
}
对于一个有n个点m条边的图,需要开一个n*m的数组存储边权,即有O(n^2)的空间复杂度,如果需要得到所有的边就需要遍历n*n数组,时间复杂度为O(n^2);因为邻接矩阵的时间空间的复杂度都较大,多数情况下效率较低,因此,存图时,更常用邻接表,如下图。
邻接表的思想是,对于一条有向边<i,j>,并不需要n*n的二维数组,只需要一个点能到达的顶点和相应的边长的集合
邻接表代码如下
#include<iostream>
#include<vector>
#define MAXN 1005;
using namespace std;
struct edge{//记录边的终点,边权的结构体
int to,cost;
} ;
int m, n;//m条边,n个点
vector <edge> p[MAXN];
int v[MAXN][MAXN];
int main(){
cin >> n >> m;
for (int i = 1;i <= m; i++){
int u, v, l;
cin >> u >> v >> l;
p[u].push_back(edge) {v, l});
/*p[u].push_back(edge) {u, l})当用无向图的邻接表时,需要加一条反方向的边
}
return 0;
}