python实现图数据结构_Python图概述,python,数据结构,与,算法,Graph,的,总结

1 基本概念

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

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

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

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

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

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

2 图的存储

2.1 邻接矩阵

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

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

2.2 邻接表

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

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

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

3 图的遍历

20200419193714713.png

"""

@Author:Lixiang

@Blog(个人博客地址): https://lixiang007.top/

@WeChat:18845312866

"""

#定义一个图的结构

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

@Blog(个人博客地址): https://lixiang007.top/

@WeChat:18845312866

"""

#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

@Blog(个人博客地址): https://lixiang007.top/

@WeChat:18845312866

"""

#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)

20200419193926182.png

4 拓扑排序

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

20200419194105447.png

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

20200419194124202.png

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

20200419194135644.png

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

20200419194156880.png

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

20200419194214232.png

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

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

5 图的最小生成树

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

5.1 普利姆算法

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

步骤

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

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

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

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

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

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

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

5.2 克鲁斯克尔(Kruskal)算法

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

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

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

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

n-1条边

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

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

AF 1;

BE 4;

BD 5;

BC 6;

DC:10;

BF 11;

DF 14;

AE 16;

AB 17;

EF 33;

算法的处理过程如下

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

DC形成环路了,舍去。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgzODc4NQ==,size_16,color_FFFFFF,t_70

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值