Python数据结构与算法——图

图的定义

图(graph) 是由一些点(vertex) 和这些点之间的连线(edge) 所组成的;其中,点通常称为顶点(vertex),而点到点之间的连线通常称之为边或者弧(edge)。通常记为G=(V,E)。

要注意的是:线性表可以是空表,树可以是空树,图不可以是空图,图可以没有边,但是至少要有一个顶点。

图的术语

顶点

顶点⼜称节点,是图的基础部分。它可以有⾃⼰的名字,我们称作“键”。顶点也可以带有附加信息,我们称作“有效载荷”。

边是图的另⼀个基础部分。两个顶点通过⼀条边相连,表⽰它们之间存在关系。边既可以是单向的,也可以是双向的。如果图中的所有边都是单向的,我们称之为有向图 。

权重

边可以带权重,⽤来表⽰从⼀个顶点到另⼀个顶点的成本。例如在路线图中,从⼀个城市到另⼀个城市,边的权重可以表⽰两个城市之间的距离。

路径

无论是无向图还是有向图,从一个顶点到另一顶点途径的所有顶点组成的序列(包含这两个顶点),称为一条路径。

如果路径中第一个顶点和最后一个顶点相同,则此路径称为"环"(或"回路")。

图的实现

可以通过多种⽅式在Python中实现图的抽象数据类型。你会看到,在使⽤不同的表达⽅式来实现图的抽象数据类型时,需要做很多取舍。有两种⾮常著名的图实现,它们分别是邻接矩阵 和邻接表 。 本节会解释这两种实现,并且⽤Python类来实现邻接表。

邻接矩阵

要实现图,最简单的⽅式就是使⽤⼆维矩阵。在矩阵实现中,每⼀⾏和每⼀列都表⽰图中的⼀个顶点。第 V ⾏和第 W 列交叉的格⼦中的值表⽰从 顶点V 到 顶点W 的边的权重。如果两个顶点被⼀条边连接起来,就称它们是相邻的。

优点

简单。对于⼩图来说,邻接矩阵可以清晰地展⽰哪些顶点是相连的。

缺点

对于存储稀疏数据来说,矩阵并不⾼效。

邻接表

为了实现稀疏连接的图,更⾼效的⽅式是使⽤邻接表。在邻接表实现中,我们为图对象的所有顶点保存⼀个主列表,同时为每⼀个顶点对象都维护⼀个列表,其中记录了与它相连的顶点。在对Vertex 类的实现中,我们使⽤字典(⽽不是列表),字典的键是顶点,值是权重。

优点

能够紧凑地表⽰稀疏图。此外,邻接表也有助于⽅便地找到与某⼀个顶点相连的其他所有顶点。

图的代码实现

1class Graph: 2 3 def __init__(self): 4 self.vertices = {} 5 self.num_of_vertices = 0 6 7 def add_vertex(self, key): 8 new_vertex = Vertex(key) 9 self.vertices[key] = new_vertex 10 self.num_of_vertices = self.num_of_vertices + 1 11 12 return new_vertex 13 14 def get_vertex(self, n): 15 if n in self.vertices: 16 return self.vertices[n] 17 return None 18 19 def contains(self, n): 20 return n in self.vertices 21 22 def add_edge(self, f, t, cost=0): 23 if f not in self.vertices: 24 new_vertex = self.add_vertex(f) 25 26 if t not in self.vertices: 27 new_vertex = self.add_vertex(t) 28 29 self.vertices[f].add_neighbor(self.vertices[t], cost) 30 31 def get_vertices(self): 32 return self.vertices.keys() 33 34 def __iter__(self): 35 return iter(self.vertices.values()) 36 37 38class Vertex: 39 40 def __init__(self, key): 41 self.id = key 42 self.connect_to = {} 43 44 def add_neighbor(self, nbr, weight=0): 45 self.connect_to[nbr] = weight 46 47 def __str__(self): 48 return str(self.id) + "connect to" + str([x.id for x in self.connect_to]) 49 50 def get_id(self): 51 return self.id 52 53 def get_connections(self): 54 return self.connect_to.keys() 55 56 def get_weight(self, nbr): 57 return self.connect_to[nbr]
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Python数据结构与算法——图 - HelloWorld