基础概念
- 假设ABCDEFG是7个电话,之间的连线表示修有通信线路
- 电话就是图的顶点vi∈V,通信线路是边ei∈E,G={V,E}就是一个图
- 只要两个电话间有线路,就可以互相通话=>无向图
- 某个电话(顶点)连接的线路(边)数量:度
- ABCDE和GF之间的消息无法传递:不连通
- ABCDE和GF是两个连通分量
- 假设ABCDE是五个电话,之间的连线表示修有通信线路,数字表示该线路的电话费
- 假设ABCDE是五个城市,带箭头连线表示该方向上有航班运营
- 例如航班A→D只能支持A飞往D,边是单向的=>有向图
- 飞来某地的航班数量:入度
- 从某地起飞的航班数量:出度
- 在一个无向图中,所有的顶点的度数之和为边数量的2倍
- 在一个有向图中,所有顶点的出度之和等于所有顶点入度之和
例题:
1.无向图G={V,E}中,|V|=n,则|E|最大为?
分析:
n个结点,每个结点都与除自己外其他结点有一条边相连,而一条边连接了两个结点,因此答案为:n(n-1)/2
答案:n(n-1)/2
图的存储结构
邻接矩阵
- 设|V|=n,图可用一个n*n方阵表示,即一个二维数组AdjMat[n][n]
- AdjMat[i][j]表示vi到vj的邻接情况
无向无权图:
- AdjMat[i][j]为1表示有边相连,为0表示无边
- AdjMat是对称的
所以设无向图对应的邻接矩阵为 A,则 A 中第 i 行上非 0 元素的个数等于第 i 列上非 0 元素的个数
有向加权图:
- AdjMat[i][j]表示vi→vj的权重
- AdjMat[i][j]为+∞表示不通
邻接表
- 每个顶点用一个链表存下自己的邻居
- |V|=n,有n个链表,即图可用一个链表的数组AdjList[n]存储
- AdjList[i]表示顶点vi的链表(头)
- 从AdjList[i]开始可以遍历所有以vi的邻居
- 设某有向图的邻接表中有 n 个表头结点和 m 个表结点,则该图中有m条有向边
邻接矩阵和邻接表的比较
- 设G={V,E}中,|V|=n.
- 邻接矩阵无论如何都需要一个二维数组[n][n],而邻接表中的每条链表长度取决于它有多少邻居
- 邻接矩阵访问AdjMat[i][j]多少O(1)D的,但邻接表访问特定边需要顺着起点的链表向后查找
- 邻接表优点:在边较少时节省许多空间=>适用于稀疏图
- 邻接表缺点:无法直接获得某条边信息,需要vi链表进行从头顺序存取,最坏O(n)
图的DFS与BFS遍历
DFS:深度优先遍历
- 遇到新的邻居就进去...直到没有可以进的邻居了再返回
- 优先进入后来遇到的邻居=>递归/栈
- 相当于二叉树的先序遍历
以B为起点进行DFS:
访问B
访问B的下一个未被访问邻居D
访问D的下一个未被访问邻居C
C所有邻居都被访问过了,返回
访问D的下一个未被访问邻居A
A所有邻居都被访问过了,返回
访问D的下一个未被访问邻居E
E所有邻居都被访问过了,返回
D所有邻居都被访问过了,返回
B所有邻居都被访问过了,当前连通图遍历完毕
BFS【Breath First Search】:广度优先遍历
- 先把当前结点的邻居都遍历完,再按先来后到遍历邻居的邻居们,逐层向外扩张
- 相当于二叉树的层序遍历
- 优先进入先访问的邻居的邻居=>队列
以B为起点进行BFS:
- 将起点B入队
- 访问当前队首B,它出队,未访问邻居D,E入队
- 访问当前队首D,它出队,未访问邻居A,C入队
- 访问当前队首E,它出队,它没有未访问邻居了
- 访问当前队首A,它出队,它没有未访问邻居了
- 访问当前队首C,它出队,它没有未访问邻居了
- 队列空了,当前连通图遍历完毕
要点:
- DFS每步操作:进入当前结点下一个未访问的邻居,如无则返回
- BFS每步操作:进入当前队首结点并让其出队,将其未访问邻居入队
1.给定如下邻接矩阵,写出由v0出发的一个DFS序列:________
A.0243156
B.0136542
C.0134256
D.0361542
分析:
(1)无需画出图结构
(2)标注已遍历过的结点
0 1 3 4 2 5 6
答案:C
2.给定如下邻接表,则由v0出发的深度优先遍历结果为(),广度优先遍历结果为()
A.0132 B.0231 C.0321 D.0123
答案:D D
生成树
- 对于含n个结点的一个无向连通图,其边数最多为n(n-1)/2条,最少为n-1条
- 保持连通性的情况下,选n-1条边出来,剔除其他边,它就变成了一棵树
- 生成树里没有环
- n结点+n-1条边+连通=>生成树
=>
最小生成树(MST)
概念:
在加权图中选出n-1条边来构成其生成树,且这些边的权值之和最小
- MST不一定唯一(如权值全相同)
求最小生成树:Prime算法
- 每次在连接已完成结点和未完成结点的边中,选一条权值最小的,重复n-1遍
- 算法利用了贪心思想:选择局部最优