一、图的定义
- 图G由顶点集V和边集E组成,记为G = (V, E),其中V(G)表示图G中顶点的有限非空集;E(G)表示图G中顶点之间的关系(边)集合。若V = { v1,v2,...,vn },则用 | V | 表示图G中顶点的个数,也称图G的阶,E = { (u,v) | u属于V,v属于V },用 | E | 表示图G中的边的条数。
- 注意:线性表可以是空表,树可以是空树,但图不可以是空,即V一定是非空集。
- 无向图:在图G中,若E是无向边(简称边)的有限集合时,则称为无向图。
- 补充:边是顶点的无序对,记为(v, w)或(w, v),因为(v, w) = (w, v),其中v, w是顶点。可以说顶点w和顶点v互为邻接点。边(v, w)依附于顶点w和顶点v,或者说边(v, w)和顶点v, w相关联。
例如图1中:
G1 = (V2, E2)
V1 = { A,B,C,D,E }
E1{ (A,B),(B,D),(B,E),(C,D),(C,E),(D,E) }
- 有向图:在图G中,若E是有向边(也称弧)的有限集合时,则称为有向图。
- 补充:弧是顶点的有序对,记为<v, w>,其中v, w是顶点,v称为弧尾,w称为弧头,<v, w>称为顶点v到顶点w的弧,也称v邻接到w,或w邻接自v。
例如图2中:
G2 = (V1, E1)
V2 = { A,B,C,D,E }
E2= { <A,B>,<A,C>,<A,D>,<A,E>,<B,A>,<B,C>,<B,E>,<C,D> }
- 简单图:1.不存在重复边。2.不存在顶点到自身的边。
- 多重图:1.图G中某两个结点之间的边数多于1条,又允许顶点通过同一条边和自己关联。
顶点的度、入度、出度
- 对于无向图:顶点v的度是指依附于该顶点的边的条数,记为TD(v)
- 对于有向图:入度是以顶点v为终点的有向边的数目,记为ID(v) 出度是以顶点v为起点的有向边的数目,记为OD(v) 顶点v的度等于其入度和出度之和,即TD(v)=ID(v)+OD(v)
- 路径:在一个图G=(V,E)中,从顶点i到顶点j的一条路径是一个顶点序列(i,i1,i2,...,j)
- 路径长度:是指一条路径上经过的边的数目
- 回路:第一个顶点和最后一个顶点相同的路径称为回路或环
- 简单路径:在路径序列中,顶点不重复出现的路径(即不含回路的路径)
- 简单回路:除了第一个顶点和最后一个顶点外,其余顶点不重复出现的回路
- 点到点的距离:从顶点u出发到顶点v的最短路径若存在,则此路径的长度称为从u到v的距离。若从u到v根本不存在路径,则记该距离为无穷。
子图:
- 设有两个图G=(V,E)和G1=(V1,E1),若V1是V的子集,即V1属于V,且E1是E的子集,即E1属于E,则称G1是G的子图。
- 生成子图:若有满足V(G1)=V(G),则称其为G的生成子图。
连通图(是对无向图而言):
- 1.在无向图G中,若从顶点i到顶点j有路径,则称顶点i和顶点j是连通的。
- 2.如果对于图中任意两个顶点都连通,则称G是连通图,否则称为非连通图。 如果G是连通图,则最少有n-1条边; 如果G是非连通图,则最多可能有;(比如一共有5个顶点,只需要拿出4个顶点并且从中任 意选取两个顶点。)
- 3.连通分量:无向图中的极大连通子图称为连通分量。 显然,连通图只有一个连通分量,就是它本身,而非连通图有多个连通分量
强连通图(是对有向图而言):
- 1.若图中任何一对顶点都是强连通的,则称此图为强连通图 注意:如果G是强连通图,则最少有n条边(形成回路)
- 2.强连通分量:有向图中的极大强连通子图。 显然,强连通图只有一个强连通分量,即本身。非强连通图有多个强连通分量
生成树:
- 连通图的生成树是包含图中全部顶点的一个极小连通子图(极小是指在这个图里面的边的数量尽可能少)
- 若图中顶点数为n,则它的生成树含有n - 1条边。对于生成树而言,若砍去它的一条边,则会变成非连通图,若加上一条边则会形成一个回路。
生成森林:
在非连通图中,连通分量的生成树构成了非连通图的生成森林。
边的权、带权图/网、带权路径长度
- 边的权:在一个图中,每条边都可以标上具有某种含义的数值,给数值称为该边的权值。
- 带权的图/网:边上带权值的图称为带权图,也称网。
- 带权路径长度:当图是带权图时,一条路径上所有边的权值之和,称为该路径的带权路径长度
几种特殊形态的图
- 完全图:若图中每两个顶点之间都存在着一条边,则称该图为完全图。
- 无向完全图:无向图中任意两个顶点之间都存在边。
- 有向完全图:有向图中任意两个顶点之间都存在方向相反的两条弧。
- 注意:完全有向图有n(n - 1)条边;完全无向图有n(n - 1) / 2条边。
- 稀疏图:边数很少的图
- 稠密图:当一个图接近完全图时,称为稠密图。
二、图的存储结构
- 基本的分为邻接矩阵和邻接表
邻接矩阵
- 邻接矩阵:是一种表示顶点之间邻接关系的矩阵
- 邻接矩阵是图的一种顺序存储结构,从邻接矩阵的行数或列数可知顶点数。
设G=(V,E)是具有n个顶点的不带权图,则G的邻接矩阵的具有如下定义的n阶方阵A
A[i][j]=1,表示有边(i,j)或者<i,j>
A[i][j]=0,表示没有边(i,j)(0<=i,j<=n-1)
A[i][i]=0,表示顶点i到自身没有边
#define MaxVertexNum 100//顶点数目的最大值
#define INFINITY 100000//宏定义常量“无穷”
typedef char VertexType;//顶点的数据类型
typedef int EdgeType;//带权图中边上权值的数据类型
typedef struct
{
VertexType vexs[MaxVertexNum];//顶点表(存放顶点)
EdgeType edges[MaxVertexNum][MaxVertexNum];//邻接矩阵,边表(存放任意两个顶点之间的距离)
int vexnum, edge;//图的当前顶点数和边数/弧数
}MGraph;
邻接矩阵的性能分析
- 空间复杂度:只和顶点数相关,和实际的边数无关
- 适合用于存储稠密图
- 无向图的邻接矩阵是对称矩阵,可以压缩存储(值存储上三角区/下三角区)
邻接表
- 邻接表是图的一种链表和顺序表相结合的存储结构
- 核心思想 : 对具有n个顶点的图建立n个线性链表存储该图
- 1.为每个顶点建立一个单链表,边结点由三个域组成,adjvex指示与顶点i邻接的顶点的编号,nextarc指向对应下一条边的节点,info存储与边相关的信息,如权值等。
- 2.表头节点有两个域组成,data存储顶点i对应的名称或其他信息,firstarc指向对应顶点i的链表中的第一个边节点。
typedef char ElemType;
typedef int InfoType;
#define MAXV 100
typedef struct ANode//边结点类型
{
int adjvex;//该边的终点位置
struct ANode* nextarc;//指向一下条边的指针
InfoType info;//该边的相关信息,如带权图可存放权重
}ArcNode;
typedef struct Vode//表头结点的类型
{
ElemType data;//顶点信息
ArcNode* firstarc;//指向第一条边
}VNode;
typedef VNode AdjList[MAXV]; //AdjList是邻接表类型
typedef struct
{
AdjList adjlist;//邻接表(表头结点组成一个数组)
int n, e;//定义顶点数和边数
}AGraph;//图的领接表类型