一、图的定义和概念
图(Graph)G由两个集合V(Vertex)和E(Edge)组成,记为 G=(V ,E)
其中V是顶点的有限集合,记为V(G),E是连接V中两个不同顶点(顶点对)的边的有限集合,记为E(G)
无向图:顶点对是无序的,顶点对用圆括号括起来
有向图:顶点对是有序的,顶点对用尖括号括起来
无向完全图:有n(n-1)/2条边的无向图
有向完全图:有n(n-1)条边的有向图
子图:有两个图G=(V , {E})和图G’=(V’, {E’}), 若V’⊆ V且E’⊆E, 则称图G’为G的子图。
顶点的度:顶点具有的边的条数
有向图中,,以顶点v为头的弧的数目,称为该顶点的入度。以顶点v为尾的弧的数目,称为该顶点的出度
权:每一条边都有与它相关的数,称为权
带权的图叫做赋权图或网
路径的长度: 路径上经过的边的数目
回路:第一个顶点和最后一个顶点相同
简单路径:表示路径的顶点序列中的顶点各不相同。
简单回路:除了第一个和最后一个顶点外,其余各顶点均不重复出现的回路
连通图:在无向图G=<V, E>中,若对任何两个顶点u、v都存在 从u到v的路径
强连通图:在有向图G=<V, E>中,若对任何两个顶点u、v都存在 从u到v的路径
连通分量:无向图中的极大连通子图
强连通分量: 有向图的极大强连通子图
生成树:连通图的生成树是⼀一个极小连通子图(含全部顶点和足以构成树的n-1条边)
二、存储结构
邻接矩阵表示法(数组表示法)

邻接矩阵特点
1.无向图的邻接矩阵一定是一个对称矩阵。因此,按照压缩存储 的思想,在具体存放邻接矩阵时只需存放上(或下)三角形阵的元素即可
2.判断两顶点v、u是否为邻接点:只需判二维数组对应分量是否为1
3.顶点不变,在图中增加、删除边:只需对二维数组对应分量赋值1或清0
4.对于无向图,邻接矩阵的第i行(或第i列)非零元素(或非∞元素)的个数正好是第i个顶点vi的度
5.对于有向图,邻接矩阵的第i行(或第i列)非零元素(或非∞元素) 的个数正好是第i个顶点vi的出度(或⼊度)
数据结构
#define MAX_VERTEX_NUM 20
#define INFINITY INT_MAX
typedef enum{//枚举类型
DG,DN,UDG,UDN
};
typedef struct ArcCell{
VRType adj;//顶点关系类型
InfoType *info;//该边权值指针
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct{
VertesType vexs[MAX_VERTEX_NUM];//顶点向量(?)
AdjMatrix arcs;
int vexnum,arcnum;
GraphKind kind;
}MGragh;
邻接表存储方法
对图中每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点vi的边(对有向图是以顶点vi为尾的弧)

特点
1.邻接表表示不惟⼀。这是因为在每个顶点对应的单链表中,各边结点的链接次序可以是任意的
2.对于无向图,邻接表的顶点vi对应的第i个链表的表结点数目正 好是顶点vi的度。
(4)对于有向图,邻接表的顶点vi对应的第i个链表的表结点数目仅仅是vi的出度。其入度为邻接表中所有adjvex域值为i的表结点数目。
数据结构
typedef struct ArcNode{//表结点
int adjvex;//邻接的结点编号
struct ArcNode *nextarc;//指向下一条边的指针
InfoType info;//边的权值
}ArcNode;
typedef struct VNode{//头结点
Vertex data;
ArcNode *firstarc;//指向第一条边
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct {
AdjList vertices;
int vexnum,arcnum;
int kind;
}ALGraph;
三、遍历
从任意给定的初始点出发,按照某种搜索方法沿着图的边访问图中所有结点,且每个顶点仅被访问一次,称为图的遍历。
分为**深度优先(DFS)和广度优先(BFS)**两种方法
深度优先搜索遍历
1)基本思想:递归
(1)访问顶点A;
(2)从A的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历;
(3)重复上面两步,直至所有顶点均被访问过。
2)辅助数组:
visited[ ]:用来记录每个顶点是否被访问过。1,访问过;0,未访问过。
3)代码:
广度优先搜索遍历
1)基本思想:
类似于树的遍历
2)代码:
四、连通性
利用图的遍历运算求解图的连通性
求无向网的最小代价生成树
由深度优先遍历得到的生成树称为深度优先生成树;由广 度优先遍历得到的生成树称为广度优先生成树
一棵生成树的代价定义为树上各边的权之总和。
代价最小的生成树称为最小代价生成树 (Minimum Cost Spanning Tree),简称为最小生成树(MST)。
求最小生成树有Prim算法和Kruskal算法
Prim算法(加点法)
1.设最小生成树的顶点集合U={U1},边集合TE={ }
2.在任一u∈U,v∈V-U 的边 ( u , v ) 中寻找代价最小的边( u’ , v’ ),将边纳入TE,v’纳入U
3.重复2操作直至U=V
Kruskal算法(加边法)
1.设最小生成树的边集合为TE={ }
2.在边集E中找到权值最小且不与TE中的边构成回路的边纳入TE,从边集E中删除该边
3.重复2操作直至E=0
五、(带权图的)最短路径
Dijkstra算法:给定点到其余各点的最短路径
1.思想:贪心算法(利用局部最优计算全局最优)
2.算法:
1)初始化:
S ← { v0 };
D[j] ← arcs[0][j], j = 1, 2, …, n-1;
2)求出最短路径的长度:
D[k] ← min{ D[i] }, i ∈ V- S ;
S ← S U { k };
3)修改:
D[i] ← min{ D[i], D[k]+arcs[k][i] },
对于每一个 i ∈ V- S ;
4)判断:若S = V, 则算法结束,否则转2) 。
Floyd算法:每对顶点之间的最短路径
定义⼀一个n阶⽅方阵序列列:
D(-1), D(0), …, D(n-1).
其中 D(-1) [i][j] = arcs[i][j](边或弧的权值);
D(k) [i][j] = Min { D(k-1) [i][j], D(k-1)[i][k] + D(k-1)[k][j] }, k = 0,1,…, n-1
(D(0) [i][j]是从顶点vi 到vj , 中间顶点是v0的最短路径的长度, D(k) [i][j]是从顶点vi 到vj , 中间顶点的序号不大于k的最短路径的 长度, D(n-1)[i][j]是从顶点vi 到vj的最短路径长度。)
本文详细介绍了图的定义,包括无向图、有向图和各种特殊图的概念。讨论了图的存储结构,如邻接矩阵和邻接表,并解析了它们的特点和数据结构。接着,概述了图的遍历方法——深度优先搜索和广度优先搜索。最后,讲解了图的连通性、最小代价生成树(Prim算法和Kruskal算法)以及最短路径问题(Dijkstra算法和Floyd算法)。
11万+

被折叠的 条评论
为什么被折叠?



