1 基本概念

无向图:即图的边没有方向,边一般用弧形括号表示()

有向图:图的边有方向,边一般用尖括号表示<>

完全图:图的每两个顶点之间有边链接

连通图:图的每两个顶点之间有路径链接

无向完全图:无向图中,任意两个顶点之间都存在边。

有向完全图:有向图中,任意两个顶点之间都存在方向互为相反的两条弧。

2 图的存储

2.1 邻接矩阵

用两个数组,一个数组保存顶点集,一个数组保存边集。

Python绘制简单有向图 python 有向图_python实现图数据结构

Python绘制简单有向图 python 有向图_数组_02

2.2 邻接表

Python绘制简单有向图 python 有向图_数组_03

对于带权值的网图,可以在边表结点定义中再增加一个weight的数据域,存储权值信息即可。

Python绘制简单有向图 python 有向图_数组_04

3 图的遍历

Python绘制简单有向图 python 有向图_python实现图数据结构_05

"""
@Author:Lixiang
"""
#定义一个图的结构
graph={
'A':['B','C'],
'B':['A','C','D'],
'C':['A','B','D','E'],
'D':['B','C','E','F'],
'E':['C','D'],
'F':['D']
}
3.1 深搜-stack实现
"""
@Author:Lixiang
"""
#DFS指的是深度优先搜索 回溯法(会回看前面的节点)
#一直往前走,走不下去往回跳
#使用stack来进行深度的顺序
#把栈顶元素去除,在把临接点放入
#其实并不难,只要把队列改成栈就可以了
def DFS(graph,s):#图 s指的是开始结点
#需要一个队列
stack=[]
stack.append(s)
seen=set()#看是否访问过
seen.add(s)
while (len(stack)>0):
#拿出邻接点
vertex=stack.pop()#这里pop参数没有0了,最后一个元素
nodes=graph[vertex]
for w in nodes:
if w not in seen:#如何判断是否访问过,使用一个数组
stack.append(w)
seen.add(w)
print(vertex)
3.2 广搜-queue实现
"""
@Author:Lixiang
"""
#BFS 广度优先搜索 层序遍历
def BFS(graph,s):#graph图 s指的是开始结点
#需要一个队列
queue=[]
queue.append(s)
seen=set()#看是否访问过该结点
seen.add(s)
while (len(queue)>0):
vertex=queue.pop(0)#保存第一结点,并弹出,方便把他下面的子节点接入
nodes=graph[vertex]#子节点的数组
for w in nodes:
if w not in seen:#判断是否访问过,使用一个数组
queue.append(w)
seen.add(w)
print(vertex)

Python绘制简单有向图 python 有向图_数组_06

4 拓扑排序

如果我们有如下的一个有向无环图,我们需要对这个图的顶点进行拓扑排序,过程如下:

Python绘制简单有向图 python 有向图_权值_07

首先,我们发现V6和v1是没有前驱的,所以我们就随机选去一个输出,我们先输出V6,删除和V6有关的边,得到如下图结果:

Python绘制简单有向图 python 有向图_权值_08

然后,我们继续寻找没有前驱的顶点,发现V1没有前驱,所以输出V1,删除和V1有关的边,得到下图的结果:

Python绘制简单有向图 python 有向图_python实现图数据结构_09

然后,我们又发现V4和V3都是没有前驱的,那么我们就随机选取一个顶点输出(具体看你实现的算法和图存储结构),我们输出V4,得到如下图结果:

Python绘制简单有向图 python 有向图_python实现图数据结构_10

然后,我们输出没有前驱的顶点V3,得到如下结果:

Python绘制简单有向图 python 有向图_数组_11

然后,我们分别输出V5和V2,最后全部顶点输出完成,该图的一个拓扑序列为:

v6–>v1—->v4—>v3—>v5—>v2

5 图的最小生成树

树是一种没有回路和环路的图

5.1 普利姆算法

Python绘制简单有向图 python 有向图_结点_12

步骤

步骤1:在所有的边中选择一个边权最小的边(如果具有相同最小权值的边有好几个,那么就随便选一个),使用这个边将两个节点连接起来,也就是将这个边加入生成树结构中

步骤2:将上述步骤中用到的点,存放在一个数组中,这个集合称之为“用过的点的集合”(一会儿我们要用这个集合来判断新选择的边是不是会构成回路)

步骤3:查找和所有已经用过的点相关的边,在这些边中挑出一个权值最小的边,加入生成树结构中,

但是在挑选的过程中我们需要保证:被选择的点,不能够出现在“用过的点的集合”中,因为如果出现这种情况,说明选择的边将使得图中出现回路,那就不是树结构了

步骤4:将这个距离最近的点,同样加入“用过的点的集合”

步骤5:重复步骤3-4,直到边的个数为节点的数量减一时候,说明所有的节点都已经加入最小生成树结构中了,程序终止

Python绘制简单有向图 python 有向图_权值_13

5.2 克鲁斯克尔(Kruskal)算法

记Graph中有v个顶点,e条边;

新建图Graphnew,Graphnew中拥有原图中的v个顶点,但没有边;

将原图Graph中所有e条边按权值从小到大排序;

循环:从权值最小的边开始,判断并添加每条边,直至添加了

n-1条边

Python绘制简单有向图 python 有向图_权值_14

图中的路径按照权值的大小的排序为

AF 1;

BE 4;

BD 5;

BC 6;

DC:10;

BF 11;

DF 14;

AE 16;

AB 17;

EF 33;

算法的处理过程如下

Python绘制简单有向图 python 有向图_python实现图数据结构_15

Python绘制简单有向图 python 有向图_结点_16

Python绘制简单有向图 python 有向图_python实现图数据结构_17

DC形成环路了,舍去。

Python绘制简单有向图 python 有向图_结点_18