图的逻辑结构为多对多,图没有顺序存储结构,但可以借助二维数组来表示元素间的关系,即数组表示法(邻接矩阵)。图的链式存储结构可以用多重链表来描述,如邻接表,邻接多重表以及十字链表等。
邻接矩阵
- 数组(邻接矩阵)表示法:
建立一个邻接表(记录各个顶点信息)和一个邻接矩阵(表示各个顶点间的关系)。
1.设图A=(V,E)有n个顶点,则有顶点表Vexs[n]如下,
i | 0 | 1 | 2 | ⋯ \cdots ⋯ | n-1 |
---|---|---|---|---|---|
Vexs[i] | v 1 v_1 v1 | v 2 v_2 v2 | v 3 v_3 v3 | ⋯ \cdots ⋯ | v n v_n vn |
2.图的邻接矩阵是一个二维数组A.arcs[n][n],定义为:
A
.
a
r
c
s
[
i
]
[
j
]
=
{
1
            
如
果
<
i
,
j
>
∈
E
或
者
(
i
,
j
)
∈
E
0
            
否
则
A.arcs[i][j] = \left\{ {\begin{array}{l} {1\;\;\;\;\;\; 如果< i,j > \in E或者(i,j) \in E}\\ {0\;\;\;\;\;\;否则} \end{array}} \right.
A.arcs[i][j]={1如果<i,j>∈E或者(i,j)∈E0否则
无向图的邻接矩阵
- 例子:
- 特点:
1.无向图的邻接矩阵是对称的,且主对角线元素全为0(因为自己到自己没有边)。
2.顶点i的度=第i行(列)中1的个数。
3.完全图的邻接矩阵中,主对角元素为0,其余全为1。
有向图的邻接矩阵
-
例子:
在有向图的邻接矩阵中,
第i行的含义:以结点 v i v_i vi为尾的弧(出度边);
第i列的含义:以结点 v i v_i vi为头的弧(入度边); -
特点:
1.有向图的邻接矩阵可能不是对称的。
2.顶点的出度=第i行元素之和;
顶点的入度=第i列元素之和;
顶点的度=第i行元素之和+第i列元素之和。
网的邻接矩阵
-
网的邻接矩阵表示法:
A . a r c s [ i ] [ j ] = { W i j              < v i , v j > 或 ( v i , v j ) ∈ V R ∞                    无 边 ( 弧 ) A.arcs[i][j] = \left\{ {\begin{array}{l} {{W_{ij}}\;\;\;\;\;\; < {v_i},{v_j} > 或({v_i},{v_j}) \in VR}\\ {\infty \;\;\;\;\;\;\;\;\;无边(弧)} \end{array}} \right. A.arcs[i][j]={Wij<vi,vj>或(vi,vj)∈VR∞无边(弧) -
例子:
邻接矩阵的具体实现
- 邻接矩阵的存储表示:用两个数组分别存储顶点表和邻接矩阵。
#define MaxInt 32767 //表示极大值,即无穷大
#define MVNum 100 //最大顶点数
typedef char VerTexType; //设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
typedef struct
{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum, arcnum; //图的当前点数和边数
}AMGraph; // Adjacency Matrix Graph
- 采用邻接矩阵表示法创建无向网
- 算法思路
- 1.输入总顶点数和总边数(为vexnum和arcnum赋值)
- 2.依次输入点的信息存入顶点表中(为vexs[i]赋值)。
- 3.初始化邻接矩阵,使每个权值初始化为极大值。
- 4.构造邻接矩阵
- 算法描述:
- 算法思路
Status CreateUDN(AMGraph &G)
{
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
for (i = 0; i < G.vexnum; ++i)
cin >> G.vexs[i]; //依次输入顶点的信息
for (i = 0; i < G.vexnum; ++i)
for (j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = MaxInt; //边的权值均置为极大值(无穷大)
for (k = 0; k < G.arcnum; ++k) //构造邻接矩阵
{
cin >> v1 >> v2 >> w; //输入一条边所依附的顶点及边的权值
i = LocateVex(G, v1);
j = LocateVex(G, v2); //确定v1和v2在G中的位置
G.arcs[i][j] = w; //边<v1,v2>的权值为w
G.arcs[j][i] = G.arcs[i][j]; //置<v1,v2>地对称边<v2,v1>的权值为w
}
return OK;
}
其中的LocateVex函数表示查找某顶点在顶点表中的位置,具体如下,
//在图G中查找顶点u,存在则返回其在顶点表中的下标,否则返回-1
int LocateVex(AMGraph G, VerTexType u)
{
int i;
for (i = 0; i < G.vexnum; ++i)
if (u == G.vexs[i])
return i;
return -1;
}
- 采用邻接矩阵表示法创建其它图
在前面创建无向网的基础上,只需经过一点修改,就可以创建无向图,有向网和有向图,操作如下图,
邻接矩阵表示法的优缺点
-
优点:
- 直观、简单、好理解
- 方便检查任意一对顶点间是否存在边
- 方便找任一顶点的所有“邻接点”(有边直接相连的顶点)
- 方便计算任一顶点的“度”。
-
缺点:
- 不便于增加和删除顶点
- 浪费空间——存稀疏图(点很多而边很少)有大量无效元素
- 对稠密图(特别是完全图)还是很合算的
- 浪费时间——统计稀疏图中一共有多少条边