一 、图相关概念介绍
1 顶点
顶点(也称“节点”)是图的基本部分。一个顶点也可能有额外的信息,将其称为“有效载荷”。
2 边
边(也称“弧”)是图的另一个基本部分。边连接两个顶点,即他们之间存在关系。边可以是单向,也可以是双向。如果图中的边都是单向的,称该图为有向图。
3 权重
边可以通过加权的形式表示从一个顶点到另一个顶点的成本。
4 图的数学定义
图 G = < V , E > G=<V,E> G=<V,E>, V V V代表顶点的集合, E E E代表边的集合。每条边是一个元组 ( v , w ) (v,w) (v,w),其中 w , v ∈ V w,v\in V w,v∈V,可以在元组中添加一维数据用来表示顶点相连边的权重。
路径
图中的路径是由边连接的顶点序列。定义一个路径为 w 1 , w 2 , . . . , w n w_1,w_2,...,w_n w1,w2,...,wn,使得 ( w i , w i + 1 ) ∈ E , 1 ≤ i ≤ n − 1 (w_i,w_{i+1})\in E,1 ≤ i ≤ n-1 (wi,wi+1)∈E,1≤i≤n−1. 未加权路径长度是路径中的边的数目,具体是 n − 1 n−1 n−1 ;加权路径长度是路径中所有边的权重的总和。
循环有向图
循环有向图中的循环是指在同一顶点开始和结束的路径。没有循环的有向图称为有向无环图或 DAG 。
二 、图抽象数据类型
Graph()
创建一个新的空图。
addVertex(vert)
向图中添加一个顶点实例。
addEdge(fromVert, toVert)
向连接两个顶点的图添加一个新的有向边。
addEdge(fromVert, toVert, weight)
向连接两个顶点的图添加一个新的加权的有向边。
getVertex(vertKey)
在图中找到名为 vertKey 的顶点。
getVertices()
返回图中所有顶点的列表。
in 返回 True 如果 vertex in graph 里给定的顶点在图中,否则返回False。
1.邻接矩阵
邻接矩阵即一个二维矩阵。每个行和列表示图中的顶点。存储在行
v
v
v 和列
w
w
w 的交叉点处的单元中的值表示是否存在从顶点
v
v
v 到顶点
w
w
w 的边。 当两个顶点通过边连接时,我们说它们相邻。单元格中的值表示从顶点
v
v
v 到顶点
w
w
w 的边的权重。
邻接矩阵的优点是简单。对于小图,很容易看到哪些节点连接到其他节点。 然而,注意矩阵中的大多数单元格是空的,我们说这个矩阵是“稀疏的”,这样会浪费内存,所以并不是一种有效的存储方式。
2.邻接表
实现稀疏连接图的更高效的方法是使用邻接表。在邻接表实现中,保存 Graph 对象中的所有顶点,然后图中的每个顶点对象维护连接到的其他顶点。 使用字典完成顶点类的实现,其中字典键是顶点,值是权重。
![](https://i-blog.csdnimg.cn/blog_migrate/1f0e078583ab0ed38a5dde11894200ec.png)
邻接表避免了邻接矩阵表示稀疏图浪费内存的缺点。
3.邻接表Python实现
创建两个类 Graph 和 Vertex 。Vertex中的每个顶点通过字典 connectedTo 来跟踪它连接的顶点和每个边的权重。
class Vertex:
def __init__(self,key):
self.id = key
self.connectedTo = {}
def addNeighbor(self,nbr,weight=0):
self.connectedTo[nbr] = weight
def __str__(self):
return str(self.id) + ' connectedTo: '+ str([x.id for x in self.connectedTo])
def getConnections(self):
return self.connectedTo.keys()
def getId(self):
return self.id
def getWeight(self,nbr):
return self.connectedTo[nbr]
class Graph:
def __init__(self):
self.vertList = {}
self.numVertices = 0
def addVertex(self,key):
self.numVertices = self.numVertices + 1
newVertex = Vertex(key)
self.vertList[key] = newVertex
return newVertex
def getVertex(self,n):
if n in self.vertList:
return self.vertList[n]
else:
return None
def __contains__(self,n):
return n in self.vertList
def addEdge(self,f,t,cost=0):
if f not in self.vertList:
nv = self.addVertex(f)
if t not in self.vertList:
nv = self.addVertex(t)
self.vertList[f].addNeighbor(self.vertList[t],cost)
def getVertices(self):
return self.vertList.keys()
def __iter__(self):
return iter(self.vertList.values())
# 实例化
g = Graph()
for i in range(6):
g.addVertex(i)
# print(g.vertList)
g.addEdge(0,1,5)
g.addEdge(0,5,2)
g.addEdge(1,2,4)
g.addEdge(2,3,9)
g.addEdge(3,4,7)
g.addEdge(3,5,3)
g.addEdge(4,0,1)
g.addEdge(5,4,8)
g.addEdge(5,2,1)
for v in g:
for w in v.getConnections():
print("(%s , %s)"%(v.getId() , w.getId()))