开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
1、写在前面
大家好,今天文章的内容是:
- 图的若干概念
2、内容
2.1、什么是图?
图()是由顶点的非空集合和边或弧的集合组成的,表示为。
一般的,我们用表示图的顶点集,用表示图的边集。
图结构是一种复杂的非线性结构,在图结构中,结点之间的关系是多对多的关系。因此图结构一般被用于描述各种复杂的数据关系,在计算机科学领域有着广泛的应用。
2.2、图的基础术语
下面记录图论的一些基本概念。
无向图
如果图中的结点对是无序的,也就是说结点之间的边是没有方向的。此时将这个图称为无向图。
边集 为无向边的集合,以无序对 表示 和 之间存在一条无向边。在无向图中边是对称的, 和 表示的是同一条边。
有向图
如果图中的顶点对是有序的,也就是说结点之间的边是有方向的,这时则称图为有向图。
边集 为有向边的集合,此时习惯上会将结点的边称为弧,并且以有序对 表示一条从顶点 出发到达顶点 的弧,其中: 称为弧尾或起点, 称为弧头或终点。在有向图中, 和 不同的两条弧。
加权图
图中的边带有某种与之相关的数值,我们称之为权值。
如果图中的边被赋予权值,那么这种图就被称为加权图。
如果图是有向的,称为加权有向图,如果是无向的,称为加权无向图。
无向完全图
如果在无向图中,任意两个顶点都有一条边直接相连,这时就称该图为无向完全图。
备注:
- 具有个顶点的无向完全图具有条边。
有向完全图
如果在有向图中,任意顶点都有一条弧直接到达其他顶点,这时就称该图为有向完全图。
备注:
- 具有个顶点的有向完全图具有条弧。
子图
给定两个图和 ,且满足条件是的子集,,且是的子集,,则称是的子图。
度
在一个图中,与顶点相关联的边的数目被称为顶点的度。
注意:
- 在无向图中,顶点的度指的是与该顶点相关联的边的数目。
- 在有向图中,顶点的度分为入度和出度。因此有向图的度等于入度和出度相加。
清楚度的概念,我们不难得出一个结论:一个具有个顶点,条边或弧的图,其顶点的度数之和就等于边数的2倍。
连通图和连通分量
这里需要清楚连通的概念。在无向图G中,若从顶点到顶点存在一条路径(),也就是这两个顶点是可达的,此时就称到是连通的。
明白什么是连通后,再看看什么是连通图。如果顶点集中的每一对不同的顶点和都连通,则称是连通图。
另外,无向图中的极大连通子图称为图的连通分量。
强连通图和强连通分量
前面已经知道了什么是连通。那么,在有向图中,如果对于中的每一对不同的顶点、()都存在从到的一条路径以及从到的一条路径,那么称该图为强连通图。
另外,有向图中极大的强连通子图称为图的强连通分量。
生成树
连通图的生成树是包含图中所有顶点的一个极小连通子图。
说明:
- 生成树的特点是含有图中全部的
n个顶点,并且只有n-1条边(n-1条边就足以构成一棵树) - 边尽可能的少,但又要保持连通。
- 因此在生成树中任意地添加一条边,必然会构成一个回路或环。
需要注意,图的生成树并不是唯一的。
有向树
只有一个顶点的入度为0,其余顶点的入度为1的有向图,称为有向树。
说明:
- 有向树是弱连通图。
- 将有向图的所有的有向边替换为无向边,所得到的图称原图的基图。
- 如果一个有向图的基图是连通图,则该有向图是弱连通图
2.3、图的抽象数据类型定义
代码如下,仅供参考:
template <class VType, class EType>
class Graph {
public:
// 返回图的顶点数
int numOfVertex() const { return verNum; }
// 返回图的边数
int numOfEdge() const { return edgeNum; }
// 创建图
virtual void createGraph(const VType V[],const EType E[])=0;
// 查找边
virtual bool searchEdge(int from, int to) const = 0;
// 插入权值为w的边
virtual bool insertEdge(int from, int to, EType w) = 0;
// 删除边
virtual bool removeEdge(int from, int to) = 0;
// 输出图
virtual void printGraph()const=0;
// 深度优先遍历
virtual void dfsTraverse()const = 0;
// 广度优先遍历
virtual void bfsTraverse()const = 0;
// 拓扑排序
virtual bool topSort()const=0;
// prim算法
virtual void prim(EType noEdge) const=0;
// kruskal算法
virtual void kruskal() const=0;
// 输出最小生成树
virtual void printMst()const=0;
protected:
int verNum, edgeNum; // 图的顶点数和边数
bool *visited; // 访问标志数组
// 最小生成树的边结点类型
struct mstEdge {
// 边的三元组(始点,终点,权值)
int vex1, vex2;
EType weight;
// 由于需要使用优先级队列,因此要重载 <
bool operator<(const mstEdge &e) const {
return weight < e.weight;
}
} *TE; // 最小生成树的边集
};
3、写在最后
好了,文章的内容就到这里,感谢观看。