图——存储及遍历
图的定义
定义:图G是由顶点集V和边集E组成,记为G=(V, E),其中V(G)表示图G
的顶点的非空有限集,E(G)表示图中的边的集合。顶点的个数称为图的阶。
基本概念:
-
有向图
-
无向图
-
简单图:如果图满如下条件则图称为简单图:(1)不存在重复边;(2)不存在顶点到自身的边;则称图为简单图。
-
多重图:若图G中某两个节点之间的边数对于一条,又允许顶点通过同一条边和自己相关联,则称图G为多重图。
-
完全图(也称简单完全图):无向图中如果任意两个顶点之间都有一条边相关联,则称图为无向完全图。在有向图中,如果任意两个顶点之间都存在方向相反的两条弧,则称该图为有向完全图。
-
子图
-
连通,连通图和连通分量:在无向图中,如果顶点v和w之间有路径存在,则称v和w是连通的,若图G中任意两个顶点都是连通的,则称图G为连通图,否则称为非连通图。无向图中的极大连通子图称为连通分量,如果图中有n个顶点,并且有小于n-1条边,则此图必是非连通图。
-
强连通图和强连通分量:在有向图中如果从顶点v到顶点w和从顶点w到顶点v之间都有路径,则称这两个顶点是强连通的。若图中任何一对顶点都是强连通的,则称此图为强连通图。
-
生成树,生成森林:生成树是包含图中所有顶点的一个极小连通子图,如果图中有n个顶点,则它的生成树含有n-1条边。
-
顶点的度,入度和出度:在无向图中,顶点的度等于边数的二倍;在有向图中度分为入度和出度,有向图中所有顶点的入度和出度之和都等于边数。
-
边的权和网:边上带有权值的图称为带权图,也称为网。
-
稠密图,稀疏图:一般当图G满足:|E| < |V|log(|V|)时,将图看成稀疏图。
-
路径,路径长度和回路:第一个顶点和最后一个顶点相同的路径称为回路或者环。
-
简单路径和简单回路:在路径序列中,顶点不重复出现的路径称为简单路径,除第一个顶点和最后一个顶点之外,其余顶点不重复的路径成为简单回路。
-
距离
-
有向树:有一个顶点入度为0,其余顶点入度为1的树称为有向树。
图的存储及基本操作
图的存储
-
邻接矩阵法
用一个一位数组存储图中顶点的信息,用一个二维数组存储图中边的信息,存储顶点之间邻接关系的二维数组称为邻接矩阵。
图的邻接矩阵的数据结构定义如下:
#define MaxVertexNum 100 //顶点的最大数目 typedef char VertexType; //顶点的数据类型 typedef int EdgeType; //带权图上边的权值的数据类型 typedef struct { VertexType Vex[MaxVertexNum] //顶点表 EdgeType Edge[MaxVertexNum][MaxVertexNum] //边表 int vexnum, edgenum; //当前顶点数和边数 }MGraph;
稠密图适合邻接矩阵法。
-
邻接表法
对图中的每一个节点建立一个单链表。
顶点表节点由节点域(data)和指向第一条邻接边的指针firstarc构成,边表由邻接节点域adjvex和指向下一条邻接边的指针域nextarc构成。图的邻接表的数据结构定义如下:
#define MaxVertexNum 100 typedef struct ArcNode { // 边表节点 int adjvex; // 该弧指向的节点的顶点的位置 struct ArcNode* nextarc; // 指向下一条弧的指针 } ArcNode; typedef struct VNode { //顶点表节点。 int data; struct VNode* firstarc; } VNode, AdjList[MaxVertexNum]; typedef struct { AdjList vnode; // 邻接表 int vernum, arcnum; } ALGraph;
-
十字链表
在十字链表中很容易找到vi为结尾的弧,和以vi为头的弧。 -
邻接多重表
图的基本操作
- 判断图G是否存在无向边<v, w>或有向边(v, w);
- 列出图G中与x邻接的边;
- 在图G中插入顶点x;
- 在图G中删除顶点x;
- 如果无向边<v, w>或有向边(v, w)不存在则插入;
- 如果无向边<v, w>或有向边(v, w)存在,则删除此边;
- 求图G中顶点x的第一个邻接点;
- 获取图G中无向边<v, w>或有向边(v, w)对应的权值;
- 设置图G中无向边<v, w>或有向边(v, w)的权值。
图的遍历
广度优先搜索BFS
广度优先搜索需要借助一个队列来实现
1. 伪代码表示如下所示:
bool visited[MAX_VERTEX_NUM];
void BFSTraverse(Graph G) {
for(int i = 0; i < G.vexnum, i++)
visited[i] = false;
for(int i = 0; i < G.vexnum, i++)
if(!visited[i])
BFS(G, i)